@Autowired 源码分析
/*
* @since 2.5
* @see AutowiredAnnotationBeanPostProcessor
* @see Qualifier
* @see Value
*/
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* <p>Defaults to {@code true}.
*/
boolean required() default true;
}
@Autowired标注在构造方法,字段,setter方法,或者是能够被Spring依赖注入的配置方法。可以选择使用JSR-330 javax.inject.Inject注解,添加了required-vs-optional的语义。
-
Autowired Constructors
在任何给定bean类中,只有一个构造方法可以将required属性设置为true来声明这个注释,以指示在作为Spring bean使用时要自动装配的构造方法。
此外,如果required属性被设置为true,那么只有一个构造方法可以用@Autowired注解。如果多个非必需的构造方法标识该注解,那么它们将被视为自动装配的候选构造方法。
通过在Spring容器中匹配bean可以满足的依赖关系最多的构造方法将被选择。
如果不存在满足匹配的候选构造方法,则将会使用primary/default 构造方法(如果存在的话)。
如果类只声明了一个构造方法,那么该构造方法总是会被使用的,尽管并没有标注@Autowired。带注释的构造方法不必是public的。
-
Autowired Fields
字段是在构建bean之后,在调用任何配置方法之前注入的。
这样的配置字段不必是public的。
-
Autowired Methods
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.
配置方法可以有任意名称和任意数量的参数。
这些参数中的每一个都将通过匹配到Spring容器中的bean来注入。
Bean属性setter方法实际上只是这种通用配置方法的一个特例。
这样的配置方法不必是public的。
-
Autowired Parameters
-
Multiple Arguments and ‘required’ Semantics
-
Autowiring Arrays, Collections, and Maps
多个同类型的Bean,直接使用@Autowired时
@Controller
public class OrderController {
@Autowired
private Coffee coffee2;
}
@Bean
public Coffee coffee() {
return new Coffee("1");
}
@Bean("coffee2")
public Coffee coffee02() {
return new Coffee("Coffee-02");
}
- 如果存在多个同类型的Bean实例,需要注意的是,在使用@Autowired注入时,会根据字段的名称去容器中找实例。所以,OrderController注入的是coffee2实例。
@Primary与@Bean,@Autowired搭配使用
@Controller
public class OrderController {
/**
* 使用@Qualifier("coffee2")就可以做到即便存在多个相同类型的Bean,也不需要根据Bean的id来调整字段的名称。
* 保持我们想要的字段名称,通过@Qualifier来指定多个相同类型Bean实例的具体实例。
*
* 注解@Autowired(required = false),required的设置仅在容器中没有对应的类型Bean才有效
* 如果存在多个相同类型的Bean,导致的无法正确注入Bean,是不会触发required的生效的。
*/
@Autowired
private Coffee coffee3;
}
@Bean
public Coffee coffee() {
return new Coffee("1");
}
@Primary
@Bean("coffee2")
public Coffee coffee02() {
return new Coffee("Coffee-02");
}
- 此时Controller,即便字段名为coffee3,同时容器里存在多个同类型的Bean,但也能正确注入Coffee实例,注入的实例为标识有@Primary的Bean。
总结
@Autowired,构造方法,方法参数,方法,字段都能从容器中获取到对应的值。
-
1)、默认优先按照类型去容器中找对应的组件,
byType
。 -
2)、如果存在多个同类型的组件,会将字段的名称作为组件的id去容器中获取,
byName
。 -
3)、注解@Autowired(required = false),required的设置仅在容器中没有对应的类型Bean才有效。
如果存在多个相同类型的Bean,导致的无法正确注入Bean,是不会触发required的生效的。
-
4)、如果只存在一个有参构造,那么该有参构造的@Autowired可以省略。
@Qualifier,指定需要注入的组件的id,而不是使用字段名来获取注入
- 使用@Qualifier(“coffee2”)就可以做到即便存在多个相同类型的Bean,也不需要根据Bean的id来调整字段的名称。
- 保持我们想要的字段名称,通过@Qualifier来指定多个相同类型Bean实例的具体实例。
- 当一个接口有多个实现的时候,用于指明具体注入哪个实现类。
@Primary,让Spring进行自动装配时,默认使用首选的Bean。
- 多与@Bean结合使用。
@Resource
-
和@Autowired效果一样,能够实现Bean的自动装配。
默认是按照Bean名称进行装配,
byName
。没有能支持@Primary的功能,也不能像@Autowired那样可以设置required值。
@Inject
- 需要导入javax.inject依赖包,和@Autowired效果一样,但同样没有可以设置required值的功能。
@Autowired是Spring定义的,@Resource和@Inject属于Java规范。