卓尔高考网

Spring IoC容器初始化源码—populateBeaninitializeBean填充Bean字段反射和setter方法依赖注入以及IoC容器初始化总结四万字

篇首语:本文由小编为大家整理,主要介绍了Spring IoC容器初始化源码—populateBeaninitializeBean填充Bean字段反射和setter方法依赖注入以及IoC容器初始化总结四万字相关的知识,希望对你有一定的参考价值。

  基于最新Spring 5.x,详细介绍了bean的“初始化过程”,主要包括applyMergedBeanDefinitionPostProcessors、populateBean、initializeBean、registerDisposableBeanIfNecessary核心方法,最后对Spring IoC容器初始化进行了总结!

  上一篇文章:Spring IoC容器初始化源码(7)—createBean实例化Bean以及构造器自动注入中,我们主要讲解了ClassPathXmlApplicationContext IoC容器初始化的refresh方法中的createBean方法的全部流程以及该方法内部的createBeanInstance方法的源码——bean的创建以及基于构造器的自动注入的过程,即bean的“实例化”
  现在我们继续向下学习refresh()方法的中的后面的内容,接下来就是bean的“初始化”过程,主要知识点包括:applyMergedBeanDefinitionPostProcessors方法查找解析各种回调注解或者自动注入注解、populateBean方法填充bean实例、initializeBean方法对bean实例进行各种回调、registerDisposableBeanIfNecessary方法尝试注册bean销毁回调方法。最后,我们会对这几篇文章讲解的Spring IoC容器初始化源码进行简单的总结!

Spring IoC容器初始化源码 系列文章

Spring IoC容器初始化源码(1)—setConfigLocations设置容器配置信息

Spring IoC容器初始化源码(2)—prepareRefresh准备刷新、obtainFreshBeanFactory加载XML资源、解析<beans/>标签

Spring IoC容器初始化源码(3)—parseDefaultElement、parseCustomElement解析默认、扩展标签,registerBeanDefinition注册Bean定义

Spring IoC容器初始化源码(4)—<context:component-scan/>标签解析、spring.components扩展点、自定义Spring命名空间扩展点

Spring IoC容器初始化源码(5)—prepareBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors方法

Spring IoC容器初始化源码(6)—finishBeanFactoryInitialization实例化Bean的整体流程以及某些扩展点

Spring IoC容器初始化源码(7)—createBean实例化Bean的整体流程以及构造器自动注入

Spring IoC容器初始化源码(8)—populateBean、initializeBean填充Bean、字段反射和setter方法依赖注入以及IoC容器初始化总结【四万字】

< context:property-placeholder/>标签以及PropertySourcesPlaceholderConfigurer占位符解析器源码深度解析

三万字的ConfigurationClassPostProcessor配置类后处理器源码深度解析

基于JavaConfig的AnnotationConfigApplicationContext IoC容器初始化源码分析

文章目录

  • Spring IoC容器初始化源码 系列文章
  • 1 applyMergedBeanDefinitionPostProcessors应用MergedBeanDefinitionPostProcessor后处理器
    • 1.1 CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition回调
      • 1.1.1 InitDestroyAnnotationBeanPostProcessor. postProcessMergedBeanDefinition回调
        • 1.1.1.1 findLifecycleMetadata处理@PostConstruct、@PreDestroy注解
          • 1.1.1.1.1 buildLifecycleMetadata创建LifecycleMetadata
          • 1.1.1.1.2 LifecycleElement生命周期回调方法包装
        • 1.1.1.2 checkConfigMembers检查配置
      • 1.1.2. findResourceMetadata处理@WebServiceRef、@EJB、@Resource注解
        • 1.1.2.1 buildResourceMetadata获取InjectionMetadata
        • 1.1.2.2 checkConfigMembers检查配置
    • 1.2 AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition回调
      • 1.2.1 findAutowiringMetadata处理@Autowired、@Value、@Inject注解
        • 1.2.1.1 buildAutowiringMetadata获取InjectionMetadata
    • 1.3 ApplicationListenerDetector.postProcessMergedBeanDefinition回调
  • 2 addSingletonFactory添加单例工厂
    • 2.1 getEarlyBeanReference回调SmartInstantiationAwareBeanPostProcessor获取早期bean引用
  • 2 populateBean填充bean实例
    • 2.1 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation回调
    • 2.2 autowireByName 基于byName的setter自动注入解析
      • 2.2.1 unsatisfiedNonSimpleProperties获取需要进行注入的非简单类型的“属性”名数组
    • 2.3 autowireByType基于byType的setter自动注入解析
    • 2.4 InstantiationAwareBeanPostProcessor.postProcessProperties回调注解注入
      • 2.4.1 InjectionMetadata.inject注解注入
      • 2.4.2 InjectedElement.inject执行@WebServiceRef、@EJB、@Resource注解解析注入
        • 2.4.2.1 @Resource注解的基本解析
        • 2.4.2.2 ResourceElement. getResourceToInject解析@Resource获取资源用于注入
          • 2.4.2.2.1 getResource获取给定名称和类型的资源对象
            • 2.4.2.2.2.1 autowireResource获取自动注入的资源
        • 2.4.2.3. checkPropertySkipping跳过属性
      • 2.4.3 AutowiredFieldElement.inject执行@Autowired、@Value、@Inject字段注解解析注入
      • 2.4.4 AutowiredMethodElement.inject执行@Autowired、@Value、@Inject方法注解解析注入
    • 2.5 applyPropertyValues属性setter装配
      • 2.5.1 setPropertyValues注入属性值
        • 2.5.1.1 setPropertyValue注入属性值
          • 2.5.1.1.1 processLocalProperty一般属性注入
  • 3 initializeBean初始化bean实例
    • 3.1 invokeAwareMethods回调Aware的方法
    • 3.2 applyBeanPostProcessorsBeforeInitialization回调BeanPostProcessor.postProcessBeforeInitialization方法
    • 3.3 invokeInitMethods回调初始化方法
    • 3.4 applyBeanPostProcessorsAfterInitialization回调BeanPostProcessor.postProcessAfterInitialization方法
  • 4 registerDisposableBeanIfNecessary注册销毁回调
    • 4.1 requiresDestruction判断是否需要销毁
      • 4.1.1 hasDestroyMethod是否具有销毁回调方法
      • 4.1.2 hasApplicableProcessors是否需要被后处理器销毁
        • 4.1.2.1 InitDestroyAnnotationBeanPostProcessor.requiresDestruction回调检查@PreDestroy注解
    • 4.2 DisposableBeanAdapter可销毁bean适配器
      • 4.2.1 inferDestroyMethodIfNecessary推断销毁方法
      • 4.2.2 filterPostProcessors过滤DestructionAwareBeanPostProcessor
    • 4.3 registerDisposableBean注册disposableBeans
  • 5 finishRefresh完成刷新
    • 5.1 clearResourceCaches清除资源缓存
    • 5.2 initLifecycleProcessor初始化生命周期处理器LifecycleProcessor
    • 5.3 onRefresh回调SmartLifecycle.start()方法
      • 5.3.1 AbstractApplicationContext.start
  • 6 IoC容器初始化总结

  我们接着上一篇文章继续向下讲doCreateBean方法在createBeanInstance之后的源码!

1 applyMergedBeanDefinitionPostProcessors应用MergedBeanDefinitionPostProcessor后处理器

  createBeanInstance实例化bean完毕之后,方法或者字段依赖注入之前,会接着调用applyMergedBeanDefinitionPostProcessors方法,正如方法名那样,这个方法将会查找全部MergedBeanDefinitionPostProcessor类型的后处理器,回调它们的postProcessMergedBeanDefinition方法,该方法可以改变已合并的bean定义,当然还能做更多的事情,最常见的就是解析字段和方法上的某些注解。
  很多的后处理器都是MergedBeanDefinitionPostProcessor的子类型,比如CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor、ApplicationListenerDetector这三个常见的后处理器,它们的postProcessMergedBeanDefinition方法都将在这里被依次回调,即在bean实例化之后被回调。

  1. CommonAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法最开始还会调用父类InitDestroyAnnotationBeanPostProcessor的同名方法用于处理方法上的@PostConstruct、@PreDestroy注解,随后自己处理字段和方法上的@WebServiceRef、@EJB、@Resource注解。
  2. AutowiredAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法用于处理方法和字段上的@Autowired、@Value、@Inject注解。
  3. ApplicationListenerDetector的postProcessMergedBeanDefinition方法用于记录ApplicationListener类型的bean是否是单例的,后面监听器过滤的时候才会用到。

  注意,在这一步(applyMergedBeanDefinitionPostProcessors方法)仅仅是简单解析这些注解,相当于查找并缓存起来,后面某些时候,比如依赖注入的时候会被再次调用,到时候将进一步深度解析它们的配置属性和功能。

/** * 将MergedBeanDefinitionPostProcessors后处理器应用于指定的 bean 定义,调用其postProcessMergedBeanDefinition方法。 * * @param mbd      已合并的bean定义 * @param beanType bean的类型 * @param beanName beanName */protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)     //获取、遍历全部已注册的后处理器    for (BeanPostProcessor bp : getBeanPostProcessors())         //如果bp属于MergedBeanDefinitionPostProcessor        if (bp instanceof MergedBeanDefinitionPostProcessor)             //那么强制转型            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;            //回调postProcessMergedBeanDefinition方法,该方法可用于修改给定bean的已合并的RootBeanDefinition            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);            

1.1 CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition回调

  该方法首先会调用父类InitDestroyAnnotationBeanPostProcessor的同名方法用于处理PostConstruct、PreDestroy注解。随后自己处理@WebServiceRef、@EJB、@Resource注解。

/** * CommonAnnotationBeanPostProcessor的方法 * 

* 调用父类InitDestroyAnnotationBeanPostProcessor的同名方法用于处理:PostConstruct、PreDestroy注解。 * 随后自己处理:@WebServiceRef、@EJB、@Resource注解。 * * @param beanDefinition 已合并的bean定义 * @param beanType bean的类型 * @param beanName beanName */@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) /*调用父类的InitDestroyAnnotationBeanPostProcessor的同名方法用于处理@PostConstruct、@PreDestroy注解*/ super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); /*自己处理@WebServiceRef、@EJB、@Resource注解*/ InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null); //检查配置 metadata.checkConfigMembers(beanDefinition);

  很多后处理器在创建的时候会初始化很多的属性,CommonAnnotationBeanPostProcessor也不例外,最重要的是它会设置父类的init 和 destroy 注解类型默认为javax.annotation.PostConstruct和javax.annotation.PreDestroy。因此我们也可以自定义初始化和销毁注解。

/** * CommonAnnotationBeanPostProcessor的构造器 * 

* 设置父类的init 和 destroy 注解类型为javax.annotation.PostConstruct和javax.annotation.PreDestroy * 因此我们也可以自定义初始化和销毁注解 */public CommonAnnotationBeanPostProcessor() //设置父类InitDestroyAnnotationBeanPostProcessor的order属性 //用于排序 setOrder(Ordered.LOWEST_PRECEDENCE - 3); //设置父类InitDestroyAnnotationBeanPostProcessor的initAnnotationType属性 //表示初始化回调注解的类型 setInitAnnotationType(PostConstruct.class); //设置父类InitDestroyAnnotationBeanPostProcessor的destroyAnnotationType属性 //表示销毁回调注解的类型 setDestroyAnnotationType(PreDestroy.class); //设置自己的ignoredResourceTypes属性 //表示在解析@Resource注解时忽略给定的资源类型。 ignoreResourceType("javax.xml.ws.WebServiceContext");

1.1.1 InitDestroyAnnotationBeanPostProcessor. postProcessMergedBeanDefinition回调

  内部就是调用两个方法,findLifecycleMetadata用于解析该Class,获取全部具有@PostConstruct、@PreDestroy注解的方法的LifecycleMetadata包装对象。
  checkConfigMembers用于检查配置信息,主要是防止后续重复调用回调方法。

/** * InitDestroyAnnotationBeanPostProcessor的方法 * 

* 处理@PostConstruct、@PreDestroy注解 * * @param beanDefinition 已合并的bean定义 * @param beanType bean的类型 * @param beanName beanName */@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) //获取生命周期相关的元数据对象,LifecycleMetadata是该类的内部类,内部持有当前的class以及对应的具有@PostConstruct、@PreDestroy注解的方法 LifecycleMetadata metadata = findLifecycleMetadata(beanType); //检查配置信息 metadata.checkConfigMembers(beanDefinition);

1.1.1.1 findLifecycleMetadata处理@PostConstruct、@PreDestroy注解

  用于获取该Class的LifecycleMetadata,内部保存了具有@PostConstruct、@PreDestroy注解的方法。
  首先尝试从lifecycleMetadataCache缓存中获取,没有缓存就进行解析,解析之后会将结果存入缓存,后续相同的Class不再解析。

/** * InitDestroyAnnotationBeanPostProcessor的方法 * 

* 获取LifecycleMetadata * * @param clazz bean的类型 * @return LifecycleMetadata对象,内部持有当前的class以及对应的具有@PostConstruct、@PreDestroy注解的方法 */private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) //如果lifecycleMetadataCache缓存为null if (this.lifecycleMetadataCache == null) // 创建该类型的LifecycleMetadata return buildLifecycleMetadata(clazz); //否则,查询缓存 LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz); //如果存在该类型的缓存,从缓存获取 if (metadata == null) synchronized (this.lifecycleMetadataCache) //加锁之后再次获取,防止并发 metadata = this.lifecycleMetadataCache.get(clazz); //如果metadata为null if (metadata == null) //那么创建该类型的LifecycleMetadata metadata = buildLifecycleMetadata(clazz); //存入缓存汇中 this.lifecycleMetadataCache.put(clazz, metadata); //返回 return metadata; //如果缓存不为null,那么直接返回缓存 return metadata;

1.1.1.1.1 buildLifecycleMetadata创建LifecycleMetadata

  关键方法就是buildLifecycleMetadata方法,用于解析该Class的LifecycleMetadata。
  大概逻辑是:遍历该Class及其父Class,查找具有@PostConstruct和@PreDestroy注解的方法,封装成为一个LifecycleElement对象,存入两个集合中,父类的回调方法的LifecycleElement在集合的前面,最后会根据该Class以及初始化、销毁集合创建一个LifecycleMetadata对象返回。

//------InitDestroyAnnotationBeanPostProcessor的相关属性------/** * 初始化回调注解的类型,默认@PostConstruct */@Nullableprivate Class<? extends Annotation> initAnnotationType;/** * 销毁回调注解的类型,默认@PreDestroy */@Nullableprivate Class<? extends Annotation> destroyAnnotationType;/** * 排序优先级 */private int order = Ordered.LOWEST_PRECEDENCE;/** 1. InitDestroyAnnotationBeanPostProcessor的方法 2. 

3. 根据给定的类型,创建LifecycleMetadata 4. 遍历该类及其父类查找初始化注解和销毁注解 5. 6. @param clazz bean的类型 7. @return LifecycleMetadata对象,内部持有当前的class以及对应的具有@PostConstruct、@PreDestroy注解的方法 */private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) //确定给定类是否是承载指定注释的候选项(在类型、方法或字段级别)。 //如果任何一个注解的全路径名都不是以"java."开始,并且该Class全路径名以"start."开始,或者Class的类型为Ordered.class,那么返回false,否则其他情况都返回true if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) //如果该类型不能承载这两个主机,那么直接返回emptyLifecycleMetadata,这是一个空的LifecycleMetadata实例 return this.emptyLifecycleMetadata; //到这里表示允许承载,那么尝试查找 //初始化回调方法集合 List<LifecycleElement> initMethods = new ArrayList<>(); //销毁回调方法集合 List<LifecycleElement> destroyMethods = new ArrayList<>(); //目标类型 Class<?> targetClass = clazz; /*循环遍历该类及其父类,直到父类为Object*/ do //当前的初始化回调方法集合 final List<LifecycleElement> currInitMethods = new ArrayList<>(); //当前的销毁回调方法集合 final List<LifecycleElement> currDestroyMethods = new ArrayList<>(); /* * 循环过滤所有的方法(不包括构造器),查找被初始化注解@PostConstruct和销毁注解@PreDestroy标注的方法 * 这两个注解都是标注在方法上的,构造器上没有标注 */ ReflectionUtils.doWithLocalMethods(targetClass, method -> //如果initAnnotationType不为null,并且存在该类型的注解 if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) //那么根据当前方法新建一个LifecycleElement,添加到currInitMethods中 //LifecycleElement表示了一个具有@PostConstruct、@PreDestroy等生命周期注解的方法 LifecycleElement element = new LifecycleElement(method); currInitMethods.add(element); if (logger.isTraceEnabled()) logger.trace("Found init method on class [" + clazz.getName() + "]: " + method); //如果initAnnotationType不为null,并且存在该类型的注解 if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) //那么根据当前方法新建一个LifecycleElement,添加到currDestroyMethods中 currDestroyMethods.add(new LifecycleElement(method)); if (logger.isTraceEnabled()) logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method); ); //currInitMethods集合整体添加到initMethods集合的开头 initMethods.addAll(0, currInitMethods); //currDestroyMethods集合整体添加到destroyMethods集合的开头 destroyMethods.addAll(currDestroyMethods); //获取下一个目标类型,是当前类型的父类型 targetClass = targetClass.getSuperclass(); //如果目标类型不为null并且不是Object.class类型,那么继续循环,否则结束循环 while (targetClass != null && targetClass != Object.class); //如果initMethods和destroyMethods都是空集合,那么返回一个空的LifecycleMetadata实例 //否则返回一个新LifecycleMetadata,包含当前的class以及对应的找到的initMethods和destroyMethods return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata : new LifecycleMetadata(clazz, initMethods, destroyMethods));

1.1.1.1.2 LifecycleElement生命周期回调方法包装

  LifecycleElementInit是DestroyAnnotationBeanPostProcessor的内部类,一个LifecycleElement对象封装了一个生命周期回调方法,及其标识符,标识符用于方法重复调用。
  在创建LifecycleElement的时候做两件事:

  1. 进行参数校验,只有0个参数的方法才能作为初始化或者销毁回调方法,否则抛出异常:Lifecycle method annotation requires a no-arg method……
  2. 计算当前方法的identifier标识符,用于避免重复调用回调方法。如果是私有方法,则标识符为该方法的全路径名;如果是非私有方法,则标识符为该方法简单名字。
/** * InitDestroyAnnotationBeanPostProcessor的内部类 * 一个LifecycleElement对象封装了一个回调方法,及其标识符,标识符用于方法重复调用 */private static class LifecycleElement     /**     * 当前方法     */    private final Method method;    /**     * 标识符     */    private final String identifier;    public LifecycleElement(Method method)         //如果方法参数不为0,那么抛出异常,从这里可知,初始化和销毁回调方法都不能有参数        if (method.getParameterCount() != 0)             throw new IllegalStateException("Lifecycle method annotation requires a no-arg method: " + method);                this.method = method;        //计算identifier        //如果是私有方法,则标识符为:该方法的全路径名,如果是非私有方法,则标识符为该方法简单名字        this.identifier = (Modifier.isPrivate(method.getModifiers()) ?                ClassUtils.getQualifiedMethodName(method) : method.getName());    

1.1.1.2 checkConfigMembers检查配置

  设置相关的方法到checkedInitMethods和checkedDestroyMethods中,后续直接调用。同时设置到mbd的externallyManagedInitMethods中,防止重复调用同一个方法,后面会讲。

//-------LifecycleMetadata的属性----------/** * 目标类型 */private final Class<?> targetClass;/** * 初始化回调方法集合 */private final Collection<LifecycleElement> initMethods;/** * 销毁回调方法集合 */private final Collection<LifecycleElement> destroyMethods;/** * 检查的初始化回调方法集合 */@Nullableprivate volatile Set<LifecycleElement> checkedInitMethods;/** * 检查的销毁回调方法集合 */@Nullableprivate volatile Set<LifecycleElement> checkedDestroyMethods;/** * LifecycleMetadata的构造器 * @param targetClass 目标类型 * @param initMethods 初始化回调方法 * @param destroyMethods 销毁回调方法 */public LifecycleMetadata(Class<?> targetClass, Collection<LifecycleElement> initMethods,                         Collection<LifecycleElement> destroyMethods)     //为属性赋值    this.targetClass = targetClass;    this.initMethods = initMethods;    this.destroyMethods = destroyMethods;/** * LifecycleMetadata的方法 *  * 检查配置,设置相关的方法到checkedInitMethods和checkedDestroyMethods中,后续直接调用 * 同时设置到mbd的externallyManagedInitMethods中,防止重复调用同一个方法 * @param beanDefinition 当前bean定义 */public void checkConfigMembers(RootBeanDefinition beanDefinition)     //创建被检查的初始化回调方法集合    Set<LifecycleElement> checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());    //遍历检查initMethods    for (LifecycleElement element : this.initMethods)         //获取标识符        String methodIdentifier = element.getIdentifier();        //如果mbd的externallyManagedInitMethods不包含当前回调方法        if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier))             //设置到mbd的externallyManagedInitMethods中            beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);            //设置到checkedInitMethods中            checkedInitMethods.add(element);            if (logger.isTraceEnabled())                 logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);                            Set<LifecycleElement> checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());    for (LifecycleElement element : this.destroyMethods)         //获取标识符        String methodIdentifier = element.getIdentifier();        //如果mbd的externallyManagedInitMethods不包含当前回调方法        if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier))             //设置到mbd的externallyManagedInitMethods中以上是关于Spring IoC容器初始化源码—populateBeaninitializeBean填充Bean字段反射和setter方法依赖注入以及IoC容器初始化总结四万字的主要内容,如果未能解决你的问题,请参考以下文章

您可能还会对下面的文章感兴趣:

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 793096019@qq.com 举报,一经查实,本站将立刻删除。