Autowire的实现原理分析,以及Spring如何处理一个Bean的注入

Spring是如何依赖注入的?

实现依赖注入的注解有Spring提供的@Autowire@Value,以及Java提供的@Resource@Inject
在这里插入图片描述

源码追踪

这里使用断点大法,对我们自定义的Bean的创建进行观察。
首先介绍自定义的Bean结构,我定义了一个Controller,里面依赖了CommonState和一个Service。
在这里插入图片描述
然后我们在AbstractAutowireCapableBeanFactorycreateBean方法中打上断点。以DEBUG模式运行。
在这里插入图片描述
在经过一通其它Bean的创建后终于到我们要观察的Bean了。

step1 resolveBeanClass()

解析MergedBeanDefinition获取我们需要的Bean类对象
在这里插入图片描述

step2 resolveBeforeInstantiation()

从名字看到是在实例化之前进行解析。Bean的创建分为Instantiate(实例化)和Initialize(初始化)。
在这里插入图片描述
从图中可以看到会调用applyBeanPostProcessorsBeforeInstantiation(),内部是给InstantiationAwareBeanPostProcessor的实现类一个机会执行postProcessBeforeInstantiation()方法
在这里插入图片描述
在这里插入图片描述
执行完发现结果为null。
在这里插入图片描述
注意这里将beforeInstantiationResolved设置为false了。然后返回null。在这里插入图片描述

step3 doCreateBean()

在这里插入图片描述
在这里插入图片描述
看到进入createBeanInstance(),内部走到instantiateBean()
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到这一步就很熟悉了,Spring获取到我们Controller的Class对象,然后通过getDeclaredConstructor()获取构造器,然后使用工具类BeanUtils::instantiateClass()实例化我们的对象。工具类内部实现就是调用ConstructornewInstance()方法反射获得实例。
在这里插入图片描述
在完成实例化后,需要将实例化的对象包装成BeanWrapper对象,并进行initBeanWrapper操作,个这个Bean增加Converter功能和注册PropertyEditorRegistrar
在这里插入图片描述
返回到doCreateBean()
在这里插入图片描述
调用applyMergedBeanDefinitionPostProcessor(),内部是给MergedBeanDefinitionPostProcessor实现类执行postProcessMergedBeanDefinition(),其中要注意的是CommonAnnotationBeanPostProcessor这个类是用来处理Java提供的依赖注入注解比如@ResourceAutowireAnnotationBeanPostProcessor是用来处理Spring提供的@Autowire,@Value等注解的。
在这里插入图片描述
在这里插入图片描述
找到AnnotationAutowireBeanPostProcessor
在这里插入图片描述
在这里插入图片描述
首先调用findAutowiringMetadata(),内部调用buildAutowiringMetadata()
在这里插入图片描述
通过doWithLocalField()doWithLocalMethod()获取依赖的类
在这里插入图片描述
这里发现已经找到statepaperService两个属性了,同时type就是类型所在的类名
在这里插入图片描述
在这里插入图片描述
返回findAutowiringMetadata(),将刚才解析的依赖元数据添加到ConcurrentHashMap缓存起来。至此,已经完成对指定类的依赖的扫描,并且将依赖做了检查并放进InjectionMetaData中。

回到doCreateBean()

populateBean()

在这里插入图片描述
AutowiredAnnotationBeanPostProcessorpostProcessProperties()
在这里插入图片描述
拿到了之前处理的InjectionMetadata,然后inject注入。
在这里插入图片描述
进入inject()
在这里插入图片描述
在这里插入图片描述
获取依赖的类型
在这里插入图片描述
在这里插入图片描述
在内部会判断已经解析的依赖中是否存在这个type,如果不存在则尝试addCandidateEntry()将这个type通过getBean()获取Bean对象,然后返回这个依赖实例。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在经过刚才的依赖对象获取后,接下来就是注入的过程
在这里插入图片描述
在这里插入图片描述
最终通过反射Field通过setter进行注入。
在这里插入图片描述

总结(图片版)

在这里插入图片描述

总结(文字版)

在Spring启动后会对ApplicationContext进行refresh,在refresh中先后完成BeanPostProcessor的注册,然后在finishBeanFactoryInitialization方法中preInitializeSingletionsDefaultListableBeanFactory持有的beanDefinitionNames进行遍历,然后getBean进行单例Bean注入IOC容器。

来到AbstactAutowireCapableBeanFactorycreateBean方法,在doCreateBean中完成Bean的实例化,依赖注入和初始化。
内部流程是:首先createInstance通过反射获取Construtor然后newInstance实例化Bean,将Bean包装成BeanWrapper,然后InitBeanWrapper完成为这个Bean增加类型转换器。
然后applyMergedBeanDefinitionPostProcessors里面CommonAnnotationBeanPostProcessorAutowiredAnnotationBeanPostProcessor会对这个Bean的依赖进行扫描,内部通过doWithLocalFielddoWithLocalMethod获取依赖的类型以及名称,然后将各个依赖封装成InjectedElement,各个InjectedElement统一封装成InjectionMetadata然后将其缓存起来等populateBean时使用。
populateBean此时才是依赖注入的关键代码,里面通过CommonAnntationBeanPostProcessorAutowiredAnnotationBeanPostProcessorpostProcessProperties方法完成依赖注入。
postProcessProperties里面会获取刚才applyMergedBeanDefinitionPostProcessor完成的InjectionMetadata然后调用inject方法,对每一个InjectedElement执行inject,内部通过beanFactory.resolveDependency获取依赖的值,如果是Bean则通过getBean获取对应的依赖类在容器中的实例,如果是@Value则会从application.properties中解析对应的值并通过ConversionService转换成对应的格式。
在完成依赖注入(populateBean)后,会调用initializeBean进行初始化。内部通过applyBeanPostProcessorBeforeInitialization完成前置处理,通过invokeInitMethod完成@BeaninitMethod= xxx()方法的调用,applyBeanPostProcessorAfterInitialization完成后置处理。
这样一个Bean就创建并初始化完成。
通过addSingleton将这个单例Bean放入DefaultSingletonBeanRegistrysingletonObjects这个ConcurrentHashMap中。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值