Home » Java » How does autowiring work in Spring?

How does autowiring work in Spring?

Posted by: admin November 2, 2017 Leave a comment

Questions:

I’m a little confused as to how the inversion of control (IoC) works in Spring.

Say I have a service class called UserServiceImpl that implements UserService interface.

How would this be @Autowired?

And in my Controllers action, how would I instantiate an instance of this service?

Would I just do the following?

UserService userService = new UserServiceImpl();
Answers:

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 of UserService, 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.
Questions:
Answers:

Depends on whether you went 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 1 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.

Questions:
Answers:

@Autowired is a 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;

    private int roll;

    // With setter and getter method

    public void showDetail() {
        System.out.println("Value of id form A class" + a.getId(););
    }
}

Questions:
Answers:

@Autowired

  • Marks a constructor, field, setter method or config method as to be
    autowired by Spring’s dependency injection facilities.

  • Only one constructor (at max) of any given bean class may carry this
    annotation, indicating the constructor to autowire when used as a
    Spring bean. Such a constructor does not have to be public.

  • Fields are injected right after construction of a bean, before any
    config methods are invoked. Such a config field does not have to be
    public.

  • Config methods may have an arbitrary name and any number of
    arguments; each of those arguments will be autowired with a matching
    bean in the Spring container. Bean property setter methods are
    effectively just a special case of such a general config method. Such
    config methods do not have to be public.

  • In the case of multiple argument methods, the ‘required’ parameter is
    applicable for all arguments.

  • In case of a Collection or Map dependency type, the container will
    autowire all beans matching the declared value type. In case of a
    Map, the keys must be declared as type String and will be resolved to
    the corresponding bean names.

Questions:
Answers:

How does @Autowired work internally?

Ex –

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 ?

Questions:
Answers:

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;

Questions:
Answers:

Spring dependency inject help you to remove coupling from your classes.
Instead of creating object like this

UserService userService = new UserServiceImpl();

You will be using this after introducing DI

@Autowired
private UserService userService;

For achieving this you need to create a bean of your service in your ServiceConfiguration file. After that you need to Import that ServiceConfiguration class to your WebApplicationConfiguration class so that you can Autowire that bean into your Controller like this.

public class AccController {

    @Autowired
    private UserService userService;
} 

You can find a java configuration based POC here
example

Questions:
Answers:

The whole concept of inversion of control means you are free from a chore to instantiate objects manually and provide all necessary dependencies.
When you annotate class with appropriate annotation (e.g. @Service) Spring will automatically instantiate object for you. If you are not familiar with annotations you can also use XML file instead. However, it’s not a bad idea to instantiate classes manually (with the new keyword) in unit tests when you don’t want to load the whole spring context.