文章目录
04-spring @Autowired和@Value原理
一、MergedBeanDefinitionPostProcessor接口
- MergedBeanDefinitionPostProcessor接口是BeanPostProcessor的一个子接口,该接口增加了一个方法,该方法在合并处理Bean定义的时候会调用,接口代码
如下和自己翻译后的注释如下。
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
*这是运行时期合并bean定义信息的的后处理器回调接口,BeanPoseProcessor的实现者可以实现这个子接口来后处理合并的bean定义信息,
*这些bean定义信息是spring的BeanFactory用来创建bean实例的,合并的bean定义信息是原始bean定义信息的处理后的拷贝。
*postProcessMergedBeanDefinition方法可以内省一些bean的定义信息,在后置处理器实例化bean之前缓存bean的元信息。也可以修改这些
*元信息,但是只能修改那些实际上被允许修改的属性。本质上讲,这只适应于Ro*otBeanDefinition自身定义的操作,而不适用于基类的属性。
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}
- 接口只定义了一个方法用来在后期处理bean的定义信息。AutowiredAnnotationBeanPostProcessor是MergedBeanDefinitionPostProcessor接口的重要实现类,
也是@Autowired和@Value功能关键接口。下面我们结合这个接口和它实现类AutowiredAnnotationBeanPostProcessor以及@Autowire,@Value注解来观察这个接口
的执行时机。
二、调试代码
2.1 测试类
@Component
public class TestController {
@Value("${testName}")
String testName;
@Autowired
TestService testService;
@Override
public String toString() {
return "TestController{" +
"testName='" + testName + '\'' +
", testService=" + testService +
'}';
}
}
@Component
public class TestService {
String id = "100";
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "TestService{" +
"id='" + id + '\'' +
'}';
}
}
@Configuration
@ComponentScan("com.intellif")
@PropertySource(value = "classpath:/application.properties")
public class MainConfig1 {
}
2.2 配置文件
testName=mopzing
2.3 测试代码
public class Test1 {
@Test
public void test01() {
ApplicationContext app = new AnnotationConfigApplicationContext(MainConfig1.class);
System.out.println("The beans in the IOC container are listed as follows: ");
//1.打印IOC容器中所有的 实例对象名称
String[] names = app.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name + " --- " + app.getBean(name));
}
((AnnotationConfigApplicationContext) app).close();
}
}
2.4 输出
- 省去了不重要的打印:
mainConfig1 --- com.intellif.config.MainConfig1$$EnhancerBySpringCGLIB$$1c480837@1ffe63b9
testController --- TestController{testName='mopzing', testService=TestService{id='100'}}
testService --- TestService{id='100'}
- 我们看到,配置通过@Value正常注入到了TestController的testName属性,TestService也通过@Autowire正常注入到了TestController。
三、断点调试
- 断点1:AbstractAutowireCapableBeanFactory#doCreateBean#553,我们在这里看到下面的代码,打了断点之后,我们debug到这里,可以看到beanName,
刚开始beanName不是我们的testController,我们可以跳过,直到beanName是testController,我们再跟进applyMergedBeanDefinitionPostProcessors这个方法,
因为我们在testController里面用到了@Autowire和@Value,我们就想看看里面是怎么处理的。
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); //line553,这里就是调用MergedBeanDefinitionPostProcessor接口的地方,再次打断点
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
- 断点2:到了testController之后,我们取消断点1,进入applyMergedBeanDefinitionPostProcessors方法,在位置
AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors#1018设置断点2,我们可以看到有很多MergedBeanDefinitionPostProcessor
类型的后处理器会轮流处理testController,我们慢慢跳过,直到AutowiredAnnotationBeanPostProcessor出现,然后跟进1020行的postProcessMergedBeanDefinition方法
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {//line 1018 设置断点2,到这里很多MergedBeanDefinitionPostProcessor类型的后处理器会轮
//流处理testController,我们慢慢跳过,直到AutowiredAnnotationBeanPostProcessor出现
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); //line 1020
}
}
}
- 跟进postProcessMergedBeanDefinition方法,我们就到了AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition#232行了
//AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
//这里面会校验这个两个字段,并把这两个字段放到checkedElements这个属性里面去(一个Map)
metadata.checkConfigMembers(beanDefinition);
}
//AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
//刚开始进来metadata获取的是null
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);//跟进这里
//buildAutowiringMetadata返回的InjectionMetadata对象,会放到injectionMetadataCache这个缓存里面,cacheKey是beanName
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
//AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
do {
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//这里findAutowiredAnnotation方法里面会判断这个字段是否包含注解,包含的话后面的currElements集合就会添加进去
//AutowiredAnnotationBeanPostProcessor在构造方法初始化的时候就会把@Autowire和@Value这两个注解添加到集合里面方便后面对字段和方法的判断。
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
//判断require是true还是false
boolean required = determineRequiredStatus(ann);
//添加到集合里面
currElements.add(new AutowiredFieldElement(field, required));
}
});
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//流程和上面类似,这里是处理方法
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
return;
}
AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod);
if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
if (Modifier.isStatic(method.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static methods: " + method);
}
return;
}
if (method.getParameterCount() == 0) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation should only be used on methods with parameters: " +
method);
}
}
boolean required = determineRequiredStatus(ann);
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
currElements.add(new AutowiredMethodElement(method, required, pd));
}
});
//到此会加入testName和testController这两个字段
elements.addAll(0, currElements);
targetClass = targetClass.getSuperclass();
}
while (targetClass != null && targetClass != Object.class);
//根据需要注入的属性字段,构造一个InjectionMetadata对象,最终这个对象会放到injectionMetadataCache这个缓存里面
return new InjectionMetadata(clazz, elements);
}
四、属性赋值
- 然后看属性赋值的地方,属性赋值不在AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors#1018,属性赋值的入口是
AbstractAutowireCapableBeanFactory#populateBean(beanName, mbd, instanceWrapper) - line578,而属性赋值实际上不是利用的
MergedBeanDefinitionPostProcessor接口的方法,属性赋值用到的接口是InstantiationAwareBeanPostProcessor,没错,我们的AutowiredAnnotationBeanPostProcessor还实现了这个接口,这个接口是bean初始化前后的回调方法(注意是初始化不是实例化,实例化的环绕回调接口是BeanPostProcessor),利用InstantiationAwareBeanPostProcessor的后置回调方法postProcessPropertyValues在populateBean里赋值,我们看源码。
AbstractAutowireCapableBeanFactory#1348行跟进postProcessPropertyValues方法,就到了
AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues#368行,我们看到刚刚进来的时候这两个字段还是null值,checkedElements是2表示有2个需要注入的字段
五、总结
- AutowiredAnnotationBeanPostProcessor实现了MergedBeanDefinitionPostProcessor接口,在postProcessMergedBeanDefinition方法里面可以修改bean的定义信息,就是在
这个方法里面处理@Autowire和@Value注解,这个处理过程主要是做字段和方法的扫描,确定哪些字段被注解标记,然后封装相关的信息,便于后面的依赖注入。 - AutowiredAnnotationBeanPostProcessor同时还间接继承了InstantiationAwareBeanPostProcessor接口,接口的postProcessAfterInstantiation和postProcessPropertyValues方法会在bean的定义信息完成之后,在赋值的入口方法populateBean里面依次调用,就是在postProcessPropertyValues里面将依赖属性和对象进行注入的。
- 本文其实只对大体流程做了简单分析,对于AutowiredAnnotationBeanPostProcessor内部源码并未进行详细的分析,该接口主要还是在内部框架使用,写代码用的不多,借此了解spring框架内部的运行流程
- 本文代码行数基于spring的5.0.6-RELEASE版本源码