详解Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理
一、spring依赖注入使用方式
- @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byType的,如果存在多个同一类型的bean,则使用@Qualifier来指定注入哪个beanName的bean。
- 与JDK的@Resource的区别:@Resource是基于bean的名字,即beanName,来从spring的IOC容器查找bean注入的,而@Autowried是基于类型byType来查找bean注入的。
- 与JDK的@Inject的区别:@Inject也是基于类型来查找bean注入的,如果需要指定名称beanName,则可以结合使用@Named注解,而@Autowired是结合@Qualifier注解来指定名称beanName。
二、spring依赖注入注解的实现原理
注解处理器
- 在spring框架内部实现当中,注解实现注入主要是通过bean后置处理器BeanPostProcessor接口的实现类来生效的。BeanPostProcessor后置处理器是在spring容器启动时,创建bean对象实例后,马上执行的,对bean对象实例进行加工处理。
- @Autowired是通过BeanPostProcessor接口的实现类AutowiredAnnotationBeanPostProcessor来实现对bean对象对其他bean对象的依赖注入的;
- @Resource和@Inject是通过BeanPostProcessor接口的实现类CommonAnnotationBeanPostProcessor来实现的,其中如名字所述,即公共注解CommonAnotation,CommonAnnotationBeanPostProcessor是spring中统一处理JDK中定义的注解的一个BeanPostProcessor。该类会处理的注解还包括@PostConstruct,@PreDestroy等。
注解处理器的激活条件
- AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor添加到spring容器的BeanPostProcessor的条件,即激活这些处理器的条件如下:
1.基于xml的spring配置
- 在对应的spring容器的配置xml文件中,如applicationContext.xml,添加<context:annotation-config />和<context:component-scan />,或者只使用<context:component-scan />。
- 两者的区别是<context:annotation-config />只查找并激活已经存在的bean,如通过xml文件的bean标签生成加载到spring容器的,而不会去扫描如@Controller等注解的bean,查找到之后进行注入;而<context:component-scan />除了具有<context:annotation-config />的功能之外,还会去加载通过basePackages属性指定的包下面的,默认为扫描@Controller,@Service,@Component,@Repository注解的类。不指定basePackages则是类路径下面,或者如果使用注解@ComponentScan方式,则是当前类所在包及其子包下面。
2.基于配置类的spring配置
- 如果是基于配置类而不是基于applicationContext.xml来对spring进行配置,如SpringBoot,则在内部使用的IOC容器实现为AnnotationConfigApplicationContext或者其派生类,在AnnotationConfigApplicationContext内部会自动创建和激活以上的BeanPostProcessor。
- 如果同时存在基于xml的配置和配置类的配置,而在注入时间方面,基于注解的注入先于基于XML的注入,所以基于XML的注入会覆盖基于注解的注入。
总结
- @Autowired是Spring自带的,@Inject和@Resource都是JDK提供的,其中@Inject是JSR330规范实现的,@Resource是JSR250规范实现的,而Spring通过BeanPostProcessor来提供对JDK规范的支持。
- @Autowired、@Inject用法基本一样,不同之处为@Autowired有一个required属性,表示该注入是否是必须的,即如果为必须的,则如果找不到对应的bean,就无法注入,无法创建当前bean。
- @Autowired、@Inject是默认按照类型匹配的,@Resource是按照名称匹配的。如在spring-boot-data项目中自动生成的redisTemplate的bean,是需要通过byName来注入的。如果需要注入该默认的,则需要使用@Resource来注入,而不是@Autowired。
- 对于@Autowire和@Inject,如果同一类型存在多个bean实例,则需要指定注入的beanName。@Autowired和@Qualifier一起使用,@Inject和@Name一起使用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
赞 (0)