直接用一些例子代码说明@Autorwired的工作原理,Spring版本为5.1.3 。
一般认为@Autorwired是自动注入的,但实际不是,和byName, byType等自动注入没有任何关系。
Ca & Cb & Cc 三个类
- Ca
public class Ca {public Ca(){System.out.println("Ca()");}/*** Autowired 是手动注入*/@AutowiredCb cb;/*** autowire inject cb only if default-autowire="byType"*/public void setXxx(Cb cb) {System.out.println("byType is ok, byName is not support:" + cb);}/*** autowire inject cb only if default-autowire="byType" or "byName"*/public void setCc(Cc cc) {System.out.println("Ca Set Cc:" + cc);}public void cbOut(){System.out.println("Cb:" + cb);}
}
- Cb
public class Cb {public Cb(){System.out.println("Cb()");}
}
- Cc
public class Cc {public Cc(){System.out.println("Cc()");}
}
自定义一个BeanFactoryPostProcessor 打印bean信息
ModeBeanFactoryPostprocessor
public class ModeBeanFactoryPostprocessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {GenericBeanDefinition ca = (GenericBeanDefinition)beanFactory.getBeanDefinition("ca");/*** 打印 Ca 的注入模型* {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}* AUTOWIRE_NO = 0;* AUTOWIRE_BY_NAME = 1;* AUTOWIRE_BY_TYPE = 2;* AUTOWIRE_CONSTRUCTOR = 3;*/System.out.println("ca autowiring mode=" + ca.getAutowireMode() + ":" + getAutowire(ca.getAutowireMode()));}private String getAutowire(int mode) {String[] arr = {"AUTOWIRE_NO", "AUTOWIRE_BY_NAME", "AUTOWIRE_BY_TYPE", "AUTOWIRE_CONSTRUCTOR", "AUTOWIRE_AUTODETECT"};return arr[mode];}
}
default-autowire=“byName”
- spring-autowired-by-name.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd"default-autowire="byName"><bean id="ca" class="com.mb.autowired.Ca" scope="singleton"></bean><bean id="cb" class="com.mb.autowired.Cb" scope="singleton"></bean><bean id="cc" class="com.mb.autowired.Cc" scope="singleton"></bean><bean id="modeBeanFactoryPostProcessor" class="com.mb.autowired.ModeBeanFactoryPostprocessor"></bean></beans>
测试
@Test
public void testAutoByName() {ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-autowired-by-name.xml");Ca ca = (Ca) applicationContext.getBean("ca");Assert.assertTrue(ca != null);ca.cbOut();
}
输出如下
可以看到没有Ca没有自动注入Cb,因为byName自动注入要求set方法为setCb()
, 而实际为setXxxx
, 不能识别
default-autowire=“byType”
- spring-autowired-by-type.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd"default-autowire="byType"><bean id="ca" class="com.mb.autowired.Ca" scope="singleton"></bean><bean id="cb" class="com.mb.autowired.Cb" scope="singleton"></bean><bean id="cc" class="com.mb.autowired.Cc" scope="singleton"></bean><bean id="modeBeanFactoryPostProcessor" class="com.mb.autowired.ModeBeanFactoryPostprocessor"></bean></beans>
当改成byType之后测试
@Test
public void testAutoByType() {ApplicationContext applicationContext =new ClassPathXmlApplicationContext("spring-autowired-by-type.xml");Ca ca = (Ca) applicationContext.getBean("ca");Assert.assertTrue(ca != null);ca.cbOut();
}
则输出如下
可以看到ca 注入cb是成功的,同时注意到@Autowired的Cb还是个null
@Autowired
Cb cb;
至少可以确认一个结论
- @Autowired和处理byType不是同一回事
@Autowired测试
接口I,及其实现类I1, I2
public interface I {
}
@Component
public class I1 implements I {public I1(){System.out.println("I1()");}
}
@Component
public class I2 implements I {public I2(){System.out.println("I2()");}
}
Ta类
@Component
public class Ta {public Ta() {System.out.println("Ta()");}@AutowiredI i1;public I getI(){return i1;}
}
自定义BeanFactoryPostProcessor打印装配方式
@Component
public class TaBeanFactoryPostprocessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {GenericBeanDefinition ta = (GenericBeanDefinition)beanFactory.getBeanDefinition("ta");/*** 打印 Ta 的注入模型* {@link org.springframework.beans.factory.config.AutowireCapableBeanFactory}* AUTOWIRE_NO = 0;* AUTOWIRE_BY_NAME = 1;* AUTOWIRE_BY_TYPE = 2;* AUTOWIRE_CONSTRUCTOR = 3;*/System.out.println("ta autowiring mode=" + ta.getAutowireMode() + ":" + getAutowire(ta.getAutowireMode()));}private String getAutowire(int mode) {String[] arr = {"AUTOWIRE_NO", "AUTOWIRE_BY_NAME", "AUTOWIRE_BY_TYPE", "AUTOWIRE_CONSTRUCTOR", "AUTOWIRE_AUTODETECT"};return arr[mode];}
}
配置扫描类
@ComponentScan("com.mb.autowired")
@Configuration
public class TaConfig {}
如上类都是com.mb.autowired
包下
AnnotationConfigApplicationContext测试代码
@Test
public void testAnnotationAutoTa() {ApplicationContext applicationContext =new AnnotationConfigApplicationContext(TaConfig.class);Ta ta = (Ta) applicationContext.getBean("ta");System.out.println("ta getI:" + ta.getI());
}
输入如下
可以看到:Ta是非自动装配的,但是确实是autowire了i1.
所以可以看到一个现象:
- @Autowired可以不是自动装配的,也可以自动注入
@Autowired原理
debugta
这个bean的初始化的populateBean阶段,可以看到if块直接跳过了,证明了确实是AUTOWIRE_NO
的
在populateBean的阶段会用InstantiationAwareBeanPostProcessor
这个BeanPostProcessor进行处理属性
继续debug会发现AutowiredAnnotationBeanPostProcessor
中
完成了注入:
AutowiredAnnotationBeanPostProcessor的处理方法
在org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
中
执行了buildAutowiringMetadata
方法找到@Autowire依赖,通过反射找到 ta @Autowire 了 i1
在org.springframework.beans.factory.annotation.InjectionMetadata.InjectedElement#inject
方法中可以看到使用了java的反射机制完成了filed的设置
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement 的 inject 方法中完成最后的注入
org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency
根据type会找到两个类型为I的bean:i1, i2
最后根据依赖的name取一个