5

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?

JoeG
  • 7,191
  • 10
  • 60
  • 105

4 Answers4

5

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.

Angular University
  • 42,341
  • 15
  • 74
  • 81
  • 3
    I both upvoted and selected this as the answer (think that is 25 points!), but the gave the bonus to Eugene as he was first with effectively the same answer - thanks for the detail! – JoeG Jan 14 '14 at 18:57
3

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.

Eugene Evdokimov
  • 2,220
  • 2
  • 28
  • 33
0

That is what the spring documentation says though right? the default is NO. So, even if you do explicitly specify it it shouldnt have any impact. Also, when you do specify a bean, what you did mention of it being Autowire.No is correct. so it shouldnt have any impact.

Hrishikesh
  • 2,033
  • 1
  • 16
  • 26
  • Added more clarification to the question. The point is that given the default behavior, other references should NOT be autowired (by name) in Java Config by default, when of course, in fact, they are. – JoeG Jan 09 '14 at 16:06
0

no The traditional Spring default.

No automagical wiring. Bean references must be defined in the XML file via the <ref/> element (or ref attribute).

We recommend this in most cases as it makes documentation more explicit.

Note that this default mode also allows for annotation-driven autowiring, if activated.

no refers to externally driven autowiring only, not affecting any autowiring demands that the bean class itself expresses

Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
Rupesh Patil
  • 109
  • 2
  • 10