spring

spring注入点元数据的缓存

2019-11-28  本文已影响0人  love111

在分析spring生命周期中属性注入方法前。有必要分析第三次后置处理器方法
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
示例代码

package com.populate;
@Component
public class B {
}

package com.populate;
@Component
public class A implements InitializingBean {
    @Autowired
    B b;

    @Autowired
    public void myMethod(){
        System.out.println("myMethod");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean");
    }

    @PostConstruct
    public void postConstru(){
        System.out.println("postConstru");
    }
}

package com;
@Configuration
@ComponentScan("com.populate")
public class AppConfig {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext( AppConfig.class );
        A a = ac.getBean( A.class );
        System.out.println( a );

缓存注入点信息

调用applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)

debug分析调用链

doCreateBean

在第二次后置处理器,通过推测构造方法创建bean对象之后(属性值是null)
AbstractAutowireCapableBeanFactory#doCreateBean


doCreateBean.png
applyMergedBeanDefinitionPostProcessors

AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
在这个方法内,将会遍历所有BeanPostProcessors(Bean后置处理器,扩展点之一):
1、ApplicationContextAwareProcessor
2、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
3、PostProcessorRegistrationDelegate$BeanPostProcessorChecker
4、CommonAnnotationBeanPostProcessor
5、AutowiredAnnotationBeanPostProcessor
6、RequiredAnnotationBeanPostProcessor
7、ApplicationListenerDetector
对于属于MergedBeanDefinitionPostProcessor类(4、5、6、7)的调用postProcessMergedBeanDefinition方法

首先看CommonAnnotationBeanPostProcessor调用分析

applyMergedBeanDefinitionPostProcessorsCommon.png
postProcessMergedBeanDefinition

CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
首先调用父类查找findLifecycleMetadata(生命周期元数据)、findResourceMetadata(Resource注解元数据)、checkConfigMembers配置信息成员检查


postProcessMergedBeanDefinition.png
applyMergedBeanDefinitionPostProcessors.png
父类postProcessMergedBeanDefinition

InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
生命周期元数据查找、配置信息成员检查


postProcessMergedBeanDefinition2.png
findLifecycleMetadata

InitDestroyAnnotationBeanPostProcessor#findLifecycleMetadata
首先从lifecycleMetadataCache缓存查找,第一次肯定为null。经过多线程双重检查查找并构建。


findLifecycleMetadata.png
buildLifecycleMetadata

InitDestroyAnnotationBeanPostProcessor#buildLifecycleMetadata
initAnnotationType表示PostConstruct注解,destroyAnnotationType表示PreDestroy注解
这里会通过lambda处理。查找是否有加了PostConstruct,PreDestroy注解的方法。最后创建LifecycleMetadata对象并返回。
结果放到lifecycleMetadataCache缓存中


buildLifecycleMetadata.png
buildLifecycleMetadata2.png

利用lambda表达式进行处理,简单说明下调用过程
首先看ReflectionUtils#doWithLocalMethods方法里面是什么

public static void doWithLocalMethods(Class<?> clazz, MethodCallback mc) {
        Method[] methods = getDeclaredMethods(clazz);
        for (Method method : methods) {
            try {
                mc.doWith(method);
            }
            catch (IllegalAccessException ex) {
                throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
            }
        }
    }

ReflectionUtils.MethodCallback里面是什么

    public interface MethodCallback {
        void doWith(Method method) throws IllegalArgumentException, IllegalAccessException;
    }

当调用到ReflectionUtils.doWithLocalMethods方法将会进入方法内,调用getDeclaredMethods会得到方法集合通过遍历methods ,调用mc.doWith(method)方法,之后便会调用到method->表达式。
为什么是这样的调用流程:可以简单的这样理解,doWithLocalMethods方法有两个参数Class、
MethodCallback。MethodCallback接口只有一个方法。所以这个lambda表达式{}就是doWith方法实现,method就是mc.doWith(method)中的参数method。doWithLocalMethods如果没有MethodCallback参数,lambda表达式可以替换mc.doWith(method)的实现

checkConfigMembers

LifecycleMetadata#checkConfigMembers


checkConfigMembers-init.png

首先通过isExternallyManagedInitMethod方法查看externallyManagedInitMethods集合中是否存在initMethod

public boolean isExternallyManagedInitMethod(String initMethod) {
        synchronized (this.postProcessingLock) {
            return (this.externallyManagedInitMethods != null &&
                    this.externallyManagedInitMethods.contains(initMethod));
        }
    }

RootBeanDefinition#registerExternallyManagedInitMethod
注册到RootBeanDefinition的externallyManagedInitMethods集合,最后也添加到当前对象的checkedInitMethods和checkedDestroyMethods集合中


registerExternallyManagedInitMethod.png
checkConfigMembers-destory.png

调用父类postProcessMergedBeanDefinition结束

findResourceMetadata

调用类似的过程,查找注入点Field和Method是否有Resource注解。构建InjectionMetadata对象返回,并放到injectionMetadataCache缓存。然后进行InjectionMetadata#checkConfigMembers方法,检查赋值等操作
CommonAnnotationBeanPostProcessor#findResourceMetadata


findResourceMetadata.png

CommonAnnotationBeanPostProcessor#buildResourceMetadata


buildResourceMetadata.png

AutowiredAnnotationBeanPostProcessor调用分析

postProcessMergedBeanDefinition

AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition


postProcessMergedBeanDefinitionautowired.png
findAutowiringMetadata

AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata


findAutowiringMetadataAutowired.png
buildAutowiringMetadata

AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata


buildAutowiringMetadataautowired.png
doWithLocalField.png
findAutowiredAnnotation

AutowiredAnnotationBeanPostProcessor#findAutowiredAnnotation
autowiredAnnotationTypes包含的注解值有Autowired、Value


findAutowiredAnnotation.png
doWithLocalMethods.png

如果方法是isStatic将会返回,报错不支持静态方法并返回
找到后构建InjectionMetadata对象返回并放到AutowiredAnnotationBeanPostProcessor#injectionMetadataCache集合

checkConfigMembers

org.springframework.beans.factory.annotation.InjectionMetadata#checkConfigMembers
从InjectionMetadata对象的injectedElements集合中遍历,放到beanDefinition的externallyManagedConfigMembers集合,之后放到checkedElements集合


checkConfigMembers.png

总结:

本章主要讨论创建bean的过程中第三次后置处理器方法,对于注入点元数据的缓存。
注入点元数据(这里1、2注入点元数据缓存,3在推测构造方法创建已经处理)
1、field属性
2、method方法
3、constructor构造方法
方法对bean后置处理器遍历并进行方法调用
主要有两个后置处理器
1、CommonAnnotationBeanPostProcessor @Resource
2、AutowiredAnnotationBeanPostProcessor @Autowired

上一篇 下一篇

猜你喜欢

热点阅读