Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Spring, what does 'autowire = Autowire.NO' do?

From this Spring documentation I know that when I use @Bean, the default is already equivalent to:

@Bean(autowire = Autowire.NO)

(Default) No autowiring. Bean references must be defined via a ref element. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.

I am just trying to understand what this means for me. If my system is 100% Java Config and has no XML configuration, then from what I can tell, when I use @Bean, the 'Autowire.no' has no impact whatsoever.

EDIT

By "no impact" I mean that other @Autowired references to this bean ARE autowired (in other Java Config classes). I suspect that is because with Java Config there is no explicit 'ref element' defined, so this (default) setting has no effect.

Example:

First Config:

package a.b.c;

@Configuration
public class AlphaConfig {

    @Bean(autowire = Autowire.NO)
    public AlphaBeanType alphaBean() {
        return new AlphaBeanType();
    }
}

Then in second config:

package d.e.f;

import a.b.c.AlphaBeanType;

@Configuration
public class AnotherConfig {

    @Autowire
    private AlphaBeanType alphaBeanType;

    @Bean
    . . .
}

What I see is that 'alphaBeanType' is always autowired in the second config class - which seems to be in conflict with the documentation - hence my question.

end edit

Of course, I can't quite tell from the documentation! Does anyone know for sure?

like image 310
JoeG Avatar asked Jan 09 '14 12:01

JoeG


2 Answers

Setting Autowire.NO does not mean that the bean cannot be injected in other beans via @Autowire. @Autowire works by default by type, and can also work by name using @Qualifier.

So if your bean has the right type or name, it will get inject in other beans, that's normal.

Autowire.NO means something like:

Don't inject the properties of THIS bean being declared with @Bean neither by type or by name. If the bean properties are not set in the @Bean method code, leave them unfilled.

This a code example of how this works, let's define two beans:

public class MyBeanTwo {

    public MyBeanTwo() {
        System.out.println(">>> MY Bean 2 created!");
    }
}

public class MyBean {

    private MyBeanTwo myBeanTwo;

    public MyBean() {
        System.out.println(">>>MyBean created !!");
    }

    public void setMyBeanTwo(MyBeanTwo myBeanTwo) {
        System.out.println(">>> Injecting MyBeanTwo INTO MyBeanOne !!!");
        this.myBeanTwo = myBeanTwo;
    }
}

And some configuration:

@Configuration
public class SimpleConfigOne {

    @Bean
    public MyBean createMyBean()   {
        return new MyBean();
    }

    @Bean
    public MyBeanTwo createMyBeanTwo() {
        return new MyBeanTwo();
    }
}

With this configuration, the startup of this application gives this log:

>>>MyBean created !!
>>> MY Bean 2 created!

Meaning one instance of each bean was created, but MyBean did NOT get injected with MyBeanTwo, even tough a bean with the correct type existed.

By declaring MyBean like this:

@Bean(autowire = Autowire.BY_TYPE)
public MyBean createMyBean()   {
    return new MyBean();
}

MyBeanOne is now eligible to have it's properties set via autowiring by type.

The startup log becomes:

>>>MyBean created !!
>>> MY Bean 2 created!
>>> Injecting MyBeanTwo INTO MyBeanOne !!!

This shows that MyBean had MyBeanTwo injected by type via a by type injection.

Reason why Autowire.NO is the default:

Usually we don't want to autowire the properties of beans created with @Bean. What we usually do is set the properties explicitly via code for readability, as a form of documentation and to make sure the property is set with the correct value.

like image 70
Angular University Avatar answered Nov 27 '22 12:11

Angular University


The autowire element of the @Bean annotation (as well as the autowire attribute of the bean element in xml-based config) determines the autowiring status of the bean's own properties and has no relation to how a bean which is marked with the @Bean annotation will be injected into other beans.

On the other hand the @Autowired annotation explicitly

marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities.

So in your case the @Bean annotation declared on the alphaBean method with the default Autowire.NO mode disables automatic (that is implicit) injection of the properties (if any) of the AlphaBeanType bean. While the @Autowired annotation indicates that an AlphaBeanType bean should be injected into AnotherConfig configuration object.

like image 27
Eugene Evdokimov Avatar answered Nov 27 '22 13:11

Eugene Evdokimov