注解@Autowired自动装配

自动装配:spring利用依赖注入(DI), 完成对IOC容器中的各个组件的依赖关系赋值

1,新建TestController.java   TestService.java  TestDao; 分别建在指定的包内,可看步骤2.

这些所有JAVA 类的对象扫描后都是保存在IOC容器中管理的;

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java

   

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_02

  

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_03

2,新建配置类Cap9MainConfig.java(),扫描并将以上bean都扫描并加载到容器

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_04

3, 针对以上基础类建立完成后, 可以先做个测试

在TestService.java, 使用Autowired注入,并把testDao打印出来(在测试时方便对比)

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_05

4, 新建Cap9Test.java测试用例,比较TestService拿到testDao与直接从容器中拿到的testDao是否为同一个?

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_06

结果很明显是同一个testDao,地址一样

小结:

@Autowired表示默认优先按类型去容器中找对应的组件,相当于anno.getBean(TestDao.class)去容器获取id为testDao的bean, 并注入到TestService的bean中;

使用方式如下:

   TestService{

        @Autowired

        private TestDao testDao;//默认去容器中找id为”testDao”的bean

   }

5, 注意事项

5.1如果容器中找到多个testDao, 会加载哪个testDao呢?

操作步骤:

在Cap9MainConfig.java声明@Bean(“testDao2”)

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_07

并将TestDao加入flag属性和set, get及toString方法,用来分辨加载了哪个bean.

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_08

如何区分TestService是使用了(@Reponstry的testDao的flag=1)的bean还是(testDao2的flag=2)的bean?

测试步骤如下:

1,直接使用@Autowired, 将testDao注入到TestService

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_09

测试结果

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_10

2,如果一定要使用容器中的testDao2呢?操作如下:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_11

测试结果:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_12

3,虽然以上定义了private TestDao testDao2, 但还是想加载bean id为testDao(flag=1)的bean,怎么办?此时可以使用@Autowired和@Qualifier结合来指定注入哪一个bean,

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_13

测试结果:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_14

4,如果容器中没有任何一个testDao, 会出现什么状况呢?

操作如下: 注释掉@Repository和@Bean("testDao2")

此时容器启动时这两个bean都不会加载(因为注解被注释啦.......)

测试结果如下:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_15

很明显报错了, ​​因为@Autowired注解里的属性默认required=true.必须找到bean​​

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_16

5,@Primary注解指定bean如何加载呢?

(:将以上原注释掉的@Repository和@Bean("testDao2") 恢复,见下图)

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_17

  

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_18

重要:为了验证@Qualifier与@Primary两注解的加载顺序,测试如下

当对于testDao在容器中同时存在多个时, 且@Qualifier与@Primary注解同时存在,会发生什么呢?

见下操作:  打开@Qualifier与@Primary注解.

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_19

  

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_20

测试结果:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_21

此时只能说明一点: @Qualifier是根据bean id指定获取testDao, 不受@Primary影响.

那么@Primary的功能在哪呢?继续测试.....

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_22

测试结果:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_23

5.2除了@Autowired, 还可以通过@Resource(JSR250)  和@Inject(JSR330)

  将Qualifier和Autowired注释掉(注意: 此时@Primary 还没注释......)

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_24

测试结果:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_25

效果也是一样的, 但它不先优先装配@Primary的bean

 

小结:@Resource和Autowired的区别如下:

@Resource和Autowired一样可以装配bean

@Resource缺点: 不能支持@Primary功能

required = false)的功能

 

当然也可以在TestService里按以下方式指定要注入的Bean

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_26

测试结果:

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_自动装配_27

5.3 @Inject自动装配的使用:

注:@Inject与@Autowired的区别如下:

@Inject和Autowired一样可以装配bean, 并支持@Primary功能, 可用于非spring框架.

@Inject缺点: 但不能支持@Autowired(required = false)的功能,需要引入第三方包javax.inject

 

操作步骤:

1,pom.xml导入javax.inject包

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_28

2,使用@Inject注解

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_java_29

结论:@Inject不支持required=false,  但支持primary

Autowired属于spring的, 不能脱离spring,  @Resource和@Inject都是JAVA规范

推荐大家使用@Autowired

@Autowired方法, 参数, 构造方法都可加载, 跟进源码看看

Spring源码分析(十) - 注解@Autowired @Resource @Qualifier @Primary  @Inject自动装配_加载_30

注意:不管@Autowired是放到参数, 方法还是构造方法, 都是从容器里取到的bean