• Spring @Autowired 原理


    主题

    学习分享记录一下Spring是怎么注入@Autowired标注的bean的.

    配置BeanPostProcessor

    传统的spring项目中配置基本是通过XML来操作的.在XML中经常会有这种配置

    <context:annotation-config/> 或者 <context:component-scan>

    或者类似的配置.这些配置是开启@Autowired等注解的关键. 先看看他们做了什么.

    解析标签

    XML中这些特殊的namespace基本都是由XXXNameSpaceHandler来做解析的

    比如AOPNamspaceHandler负责解析 <aop:aspectj-autoproxy /> 等命名空间

    类似的context:XXX这种命名空间基本是由ContextNamespaceHandler来做处理.

    他会解析一大堆标签,其中我们主要要研究的额就是component-scan和annotation-config...功能有一部分重叠.

    ComponentScanBeanDefinitionParser的parse方法会调用org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 这个方法

     

     看方法内部不难看出它往registry(BeanFactory)中添加了很多特殊的BeanPostProcessor (或者其子类).我们比较关心的是AutowiredAnnotationBeanPostProcessor

    BeanPostProcessor

    BPP这些特殊的bean会参与Spring的生命周期.

    这个类最重要的地方在于impl了InstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor了.

    其中有3个方法的覆盖比较关键.

    第一个是MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition

    这个时间点大致是在BeanFactory准备根据beanDifinition去创建bean的时候.会回调这个方法.

    AutowiredAnnotationBeanPostProcessor在这一步骤中取查找bean有标记了@Autowired的field,method等InjectionMetadata.InjectedElement的实现..

    具体的业务逻辑就不想详细说明了.基本就是通过反射去查找要注入的元素,然后封装到元信息里保存下来.


    第二个是InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation返回为true.(常规的bean都会返回true)

    InstantiationAwareBeanPostProcessor可以通过这个false参数来阻止属性的注入.

    当然正常情况下这里一般方式(比如XML中注入属性)也是允许的,所以这里返回true.这就意味着bean定义和bean的部分属性可以定义在XML中走一般的属性注入.

    而这个bean的部分属性加上@Autowired,通过注解注入也是可以的..只是可能很少会有人这么做.

    当然,设置为false的话@Autowired也不能注入.因为有短路原则.满足这种情况的话只有BeanPostProcessor.postProcessAfterInitialization会被调用.

    第三个方法是InstantiationAwareBeanPostProcessor.postProcessPropertyValues

    这个回调函数发生的时间是在BeanFactory去populateBean的时候.也就是说bean已经new了.正在初始化他的属性,且通过正常方式(比如XML里定义的属性)已经完成的时候.

     通过获取之前第一步中记录下来的metaData.InjectedElement.对于每一个element去掉inject方法.

     method和field因为是2种实现类.所以方法实现会有一点点区别.但是大致还是一样的...可以来看看field的.

    最核心的也就是.问BF去取bean.

    我有一个field.我有一个需要的type.你BF找到bean给我..就这样.

    https://www.cnblogs.com/binarylei/p/12337145.html

    可以参考上面这篇文章怎么从BF中取bean.

    绝大部分情况下基本就是从BeanDifination中取出类型匹配的bean的name.然后再去找对应的bean.

    找到了bean以后就通过field.set去设置一下即可.

    小结

    1.Spring中这么多骚操作离不开BeanPostProcessor等特殊的bean.在XML对应的applicationContext的时候通过NamspaceHandler解析XML节点,并去注册AutowiredAnnotationBeanPostProcessor等bean.

    2.AutowiredAnnotationBeanPostProcessor

    通过MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition在doCreateBean当前bean的时候收集当前的需要@Auwotired的element的元数据信息

    通过InstantiationAwareBeanPostProcessor.postProcessPropertyValues在populateBean的时候,即设置当前bean的属性的时候获取之前的需要注入的elment.然后去BF中获取对应的bean.并set.

  • 相关阅读:
    19-1 在页面中渲染基本的组件
    19 使用Vue实例的render方法渲染组件
    17 webpack中babel的配置
    前端待复习汇总
    301,302,303,307重定向区别
    尾递归
    Binary-to-text ecoding:
    object Object {} any unknown
    Vue中的model
    全局namespace与模块内的namespace
  • 原文地址:https://www.cnblogs.com/abcwt112/p/12541783.html
Copyright © 2020-2023  润新知