The 5 Minute Guide to Autowire in Spring

What is Autowiring in Spring?

Autowiring makes dependency injection even easier in Spring...

Preface: Dependency Injection in Spring

Remember that Spring uses dependency injection (DI) to achieve inversion of control (IoC) in Java applications. Using DI, it’s easier to decouple execution from implementation…

Without DI

public class A {
    private B b;
    
    public A(){
        this.b = new B();
    }
}

With DI

public class A {
    private B b;
    
    public A(B b){
        this.b = b;
    }
}

Notice how dependency injection “inverts the control” of how things get implemented to other classes. Class A isn’t responsible for how B gets created with DI.

Why we use Autowiring in Spring

Remember that Spring registers classes as beans to manage an IoC container of objects and dependencies. We use Autowiring in Spring to make DI easier for these Spring managed objects.

DI Without Autowiring

public class A {
    public B b;

    public void setB(B b){
	this.b = b;
    }
}
public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
    A a = context.getBean(A.class);
    B b = context.getBean(B.class);
    a.setB(b);
    a.b; //returns b
}

DI With Autowiring

@Component
public class A {
    @Autowired
    public B b;
}
public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
    A a = context.getBean(A.class);
    a.b; //returns b
}

Notice how we don’t need a setter method with autowiring. Since A and B are both Spring managed beans, Spring will automatically inject B into A without us having to explicitly set the property.

Remember that autowiring only works with Spring managed beans. Notice how we annotate our example classes with @Component. This registers our class as a Spring bean.

Autowiring automatically wires managed beans with other managed beans.

Autowiring makes DI even easier with Spring applications because you don’t have to explicitly inject managed dependencies. Spring can automatically figure this out at runtime and save you some boilerplate code.

@Autowired in Spring Boot | Examples

You can use the @Autowired annotation on setters, properties, and constructors.

@Autowired on Setter Methods

@Component
public class A {
    private B b;

    public B getB(){
        return this.b;
    }

    @Autowired
    public void setB(B b){
        this.b = b;
    }
}

When annotated with @Autowired, the setter method will be called automatically when A is initialized. It will pass the Spring managed B as an argument.

When is this useful?

Annotating setter methods with @Autowired removes the need to explicitly set B when initializing A.

@Autowired on Properties

@Component
public class A {
    @Autowired
    private B b;

    public B getB(){
        return this.b;
    }
}

Notice how no setter method is defined when we annotate a property with @Autowired. This is because Spring automatically sets property B with the Spring managed B dependency.

When is this useful?

Annotating properties with @Autowired makes sense when you want to automatically set managed dependencies AFTER the class is initialized.

@Autowired on Constructors

@Component
public class A {
    private B b;

    @Autowired
    public A(B b){
        this.b = b;
    }

    public B getB(){
        return this.b;
    }
}

Annotating constructors with @Autowired will automatically inject Spring managed B when B is initialized.

When is this useful?

This is preferable because managed dependencies are explicitly required for creating A. This makes testing easier because you avoid unset dependencies and ensures you don’t have any surprise runtime exceptions if B isn’t managed or instantiated.

Even more magic…

Starting with Spring 4.3, you don’t even need the @Autowired annotation on constructors. If your bean only has one constructor with managed bean arguments, Spring will automatically inject the managed dependencies even without the annotation.

@Autowired with @Qualifier

@Component(value="square")
public class Square implements Shape {
    public int getCorners(){
        return 4;
    }
}
@Component(value="triangle")
public class Triangle implements Shape {
    public int getCorners(){
        return 3;
    }
}
@Component
public class ShapeService {
    @Autowired
    @Qualifier("triangle")
    private Shape shape;
}

By default, Spring searches for autowired dependencies by type. Since both Square and Triangle implement the same type Shape we use @Qualifier to specify the name. This helps Spring identify the right bean to autowire.

Autowire in Spring Boot not working?

Beans must be Spring managed

Remember that autowiring only works with Spring managed beans. Notice how all of the examples annotate classes with @Component. This registers the classes as managed beans.

When Spring sees @Autowired it looks for a registered bean having the same type (or name if using @Qualifier). If the IoC container can’t find a matching bean it will throw an exception.

In short, @Autowired only works with registered beans via @Component, @Bean, etc.

Component scanning

Spring comes with a lot of out-of-the-box magic that minimizes the configuration needed to start development. For example, the @SpringBootApplication annotation will automatically bootstrap your application with @Configuration, @ComponentScan.

The @Autowired annotation only works if annotation-driven injection is enabled. Make sure that all of your beans/classes are being scanned to enable annotation-driven injection. If Spring isn’t scanning the right classes it won’t autowire those dependencies.

Conclusion

Autowiring makes DI even easier. Using the @Autowired annotation on setters, properties, and constructors can save you some boilerplate code when injecting Spring managed dependencies.

Your thoughts?