How does autowiring work in Spring?
Solution 1
First, and most important - all Spring beans are managed - they "live" inside a container, called "application context".
Second, each application has an entry point to that context. Web applications have a Servlet, JSF uses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans - autowired. In web applications this can be a startup listener.
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
What is "living" in the application context? This means that the context instantiates the objects, not you. I.e. - you never make new UserServiceImpl()
- the container finds each injection point and sets an instance there.
In your controllers, you just have the following:
@Controller // Defines that this class is a spring bean
@RequestMapping("/users")
public class SomeController {
// Tells the application context to inject an instance of UserService here
@Autowired
private UserService userService;
@RequestMapping("/login")
public void login(@RequestParam("username") String username,
@RequestParam("password") String password) {
// The UserServiceImpl is already injected and you can use it
userService.login(username, password);
}
}
A few notes:
- In your
applicationContext.xml
you should enable the<context:component-scan>
so that classes are scanned for the@Controller
,@Service
, etc. annotations. - The entry point for a Spring-MVC application is the DispatcherServlet, but it is hidden from you, and hence the direct interaction and bootstrapping of the application context happens behind the scene.
-
UserServiceImpl
should also be defined as bean - either using<bean id=".." class="..">
or using the@Service
annotation. Since it will be the only implementor ofUserService
, it will be injected. - Apart from the
@Autowired
annotation, Spring can use XML-configurable autowiring. In that case all fields that have a name or type that matches with an existing bean automatically get a bean injected. In fact, that was the initial idea of autowiring - to have fields injected with dependencies without any configuration. Other annotations like@Inject
,@Resource
can also be used.
Solution 2
Depends on whether you want the annotations route or the bean XML definition route.
Say you had the beans defined in your applicationContext.xml
:
<beans ...>
<bean id="userService" class="com.foo.UserServiceImpl"/>
<bean id="fooController" class="com.foo.FooController"/>
</beans>
The autowiring happens when the application starts up. So, in fooController
, which for arguments sake wants to use the UserServiceImpl
class, you'd annotate it as follows:
public class FooController {
// You could also annotate the setUserService method instead of this
@Autowired
private UserService userService;
// rest of class goes here
}
When it sees @Autowired
, Spring will look for a class that matches the property in the applicationContext
, and inject it automatically. If you have more than one UserService
bean, then you'll have to qualify which one it should use.
If you do the following:
UserService service = new UserServiceImpl();
It will not pick up the @Autowired
unless you set it yourself.
Solution 3
@Autowired
is an annotation introduced in Spring 2.5, and it's used only for injection.
For example:
class A {
private int id;
// With setter and getter method
}
class B {
private String name;
@Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods.
A a;
// With setter and getter method
public void showDetail() {
System.out.println("Value of id form A class" + a.getId(););
}
}
Solution 4
How does @Autowired
work internally?
Example:
class EnglishGreeting {
private Greeting greeting;
//setter and getter
}
class Greeting {
private String message;
//setter and getter
}
.xml file it will look alike if not using @Autowired
:
<bean id="englishGreeting" class="com.bean.EnglishGreeting">
<property name="greeting" ref="greeting"/>
</bean>
<bean id="greeting" class="com.bean.Greeting">
<property name="message" value="Hello World"/>
</bean>
If you are using @Autowired
then:
class EnglishGreeting {
@Autowired //so automatically based on the name it will identify the bean and inject.
private Greeting greeting;
//setter and getter
}
.xml file it will look alike if not using @Autowired
:
<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>
<bean id="greeting" class="com.bean.Greeting">
<property name="message" value="Hello World"/>
</bean>
If still have some doubt then go through below live demo
How does @Autowired work internally ?
Solution 5
You just need to annotate your service class UserServiceImpl
with annotation:
@Service("userService")
Spring container will take care of the life cycle of this class as it register as service.
Then in your controller you can auto wire (instantiate) it and use its functionality:
@Autowired
UserService userService;
Comments
-
Blankman almost 4 years
I'm a little confused as to how the inversion of control (
IoC
) works inSpring
.Say I have a service class called
UserServiceImpl
that implementsUserService
interface.How would this be
@Autowired
?And in my
Controllers
, how would Iinstantiate
aninstance
of this service?Would I just do the following?
UserService userService = new UserServiceImpl();
-
Blankman almost 14 yearsyour last point, so in the implmentation of the interface, UserServiceImpl, I annotate with @Service correct? Great answer, REALLY cleared things up for me.
-
Blankman almost 14 yearsis UserService userService the interface?
-
Bozho almost 14 yearsyes, UserServiceImpl is annotated with Service, and UserService is the interface
-
theJava over 13 yearsi tried to implement your post, but was not successful...stackoverflow.com/questions/4572850/autowiring-does-not-work could you look into this post
-
Tarun Kumar over 11 yearsIt's been more than 3 years since last post on this thread, I just jumped on it when looking for similar question. One query i have is, at context instantiation time, it will create only one bean object (Pls correct me if i am wrong). What if i am autowiring same bean twice in my code, will 2nd object be lazily insantiated?
-
Bozho over 11 yearsthe default scope is singleton, so you will have only one instance of the bean, which is injected in multiple places. If you explicitly define the scope to be "prototype", then multiple instances will exist, possibly lazy (depending on configuration)
-
Shishigami over 10 yearsThanks a lot for your post, it really cleared things up for me. Regarding 'Since it will be the only implementor or UserService, it will be injected.' - what if there's multiple classes that implement Userservice? How does Spring know which implementation it should use?
-
Bozho over 10 yearsif there's one designated as "primary", it uses it. Otherwise it throws an exception
-
Dmitry Minkovsky over 9 yearsThis won't compile and is generally incorrect.
@Autowired
does not mean that "you can use all the function(method) and variable inB
class from classA
". What it does is brings an instance ofA
into instances ofB
, so you can doa.getId()
fromB
. -
LifeAndHope almost 9 years@Bozho, So everytime the function
login
is called, is a newuserService
being created? Does autowiring in spring relieve the coder from creating a Singleton object? -
John Doe almost 9 years@dimadima So if he does System.out.println("Value of id form A class" + a.getId());, and not as he has actually done it will be more correct. Please do reply, as this one is intuitively clear to me and as per my current level of understanding is explaining Autowiring.
-
Bozho almost 9 yearsno, userService is created only once, it's in singleton-scope
-
SpringLearner over 8 yearsautowired annotation is introduced in spring 2.5 docs.spring.io/spring-framework/docs/2.5.x/api/org/…
-
viper almost 8 yearsSo what is the use of defining
bean id
inapplicationContext.xml
. We will have to define theuserService
variable withUserService
type. So why make entry inxml
file. -
Sameer over 7 yearsFor better understadin as I am new to this, will @autowired instantiate the Class A using the default constructor? IF not, how to values get instantiated in a bean or service if we use autowired. I guess if it calls default constructor, why use autowiring in the first place, just do A a = new A(). Please clarify?
-
kiltek almost 7 years@Sameer By Autowiring dependencies you can save a lot of boilerplate code in your Unit Tests and also Controller, Service and Dao Classes, because the instantiation of the fields come with it automatically. No need to call the constructor.
-
Matt about 6 yearsThere are way, way too many ways to do the same thing in Spring. No wonder no one gets it.
-
Jerome L about 6 yearsTrue, we've compiled some of there in our Spring Autowiring article.
-
AbhishekB almost 5 yearsClass A is not a Spring bean. How are you auto-wiring it in Class B?
-
Tarnished-Coder about 3 yearsWhy create a constructor for main class? and not autowire the declaration?
-
Madhu Nair over 2 years@viper he is talking about interfacing it i believe