Spring是如何依赖注入的?
实现依赖注入的注解有Spring提供的@Autowire
,@Value
,以及Java提供的@Resource
,@Inject
源码追踪
这里使用断点大法,对我们自定义的Bean的创建进行观察。
首先介绍自定义的Bean结构,我定义了一个Controller,里面依赖了CommonState和一个Service。
然后我们在AbstractAutowireCapableBeanFactory
的createBean
方法中打上断点。以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()
实例化我们的对象。工具类内部实现就是调用Constructor
的newInstance()
方法反射获得实例。
在完成实例化后,需要将实例化的对象包装成BeanWrapper
对象,并进行initBeanWrapper
操作,个这个Bean增加Converter功能和注册PropertyEditorRegistrar
。
返回到doCreateBean()
调用applyMergedBeanDefinitionPostProcessor()
,内部是给MergedBeanDefinitionPostProcessor
实现类执行postProcessMergedBeanDefinition()
,其中要注意的是CommonAnnotationBeanPostProcessor
这个类是用来处理Java提供的依赖注入注解比如@Resource
,AutowireAnnotationBeanPostProcessor
是用来处理Spring
提供的@Autowire,@Value
等注解的。
找到AnnotationAutowireBeanPostProcessor
首先调用findAutowiringMetadata()
,内部调用buildAutowiringMetadata()
通过doWithLocalField()
和doWithLocalMethod()
获取依赖的类
这里发现已经找到state
和paperService
两个属性了,同时type就是类型所在的类名
返回findAutowiringMetadata()
,将刚才解析的依赖元数据添加到ConcurrentHashMap
缓存起来。至此,已经完成对指定类的依赖的扫描,并且将依赖做了检查并放进InjectionMetaData
中。
回到doCreateBean()
populateBean()
AutowiredAnnotationBeanPostProcessor
的postProcessProperties()
拿到了之前处理的InjectionMetadata
,然后inject
注入。
进入inject()
获取依赖的类型
在内部会判断已经解析的依赖中是否存在这个type,如果不存在则尝试addCandidateEntry()
将这个type通过getBean()
获取Bean对象,然后返回这个依赖实例。
在经过刚才的依赖对象获取后,接下来就是注入的过程
最终通过反射Field通过setter进行注入。
总结(图片版)
总结(文字版)
在Spring启动后会对ApplicationContext
进行refresh
,在refresh
中先后完成BeanPostProcessor
的注册,然后在finishBeanFactoryInitialization
方法中preInitializeSingletions
对DefaultListableBeanFactory
持有的beanDefinitionNames
进行遍历,然后getBean
进行单例Bean注入IOC容器。
来到AbstactAutowireCapableBeanFactory
的createBean
方法,在doCreateBean
中完成Bean的实例化,依赖注入和初始化。
内部流程是:首先createInstance
通过反射获取Construtor
然后newInstance
实例化Bean,将Bean包装成BeanWrapper
,然后InitBeanWrapper
完成为这个Bean增加类型转换器。
然后applyMergedBeanDefinitionPostProcessors
里面CommonAnnotationBeanPostProcessor
和AutowiredAnnotationBeanPostProcessor
会对这个Bean的依赖进行扫描,内部通过doWithLocalField
和doWithLocalMethod
获取依赖的类型以及名称,然后将各个依赖封装成InjectedElement
,各个InjectedElement
统一封装成InjectionMetadata
然后将其缓存起来等populateBean
时使用。
populateBean
此时才是依赖注入的关键代码,里面通过CommonAnntationBeanPostProcessor
和AutowiredAnnotationBeanPostProcessor
的postProcessProperties
方法完成依赖注入。
postProcessProperties
里面会获取刚才applyMergedBeanDefinitionPostProcessor
完成的InjectionMetadata
然后调用inject
方法,对每一个InjectedElement
执行inject
,内部通过beanFactory.resolveDependency
获取依赖的值,如果是Bean则通过getBean
获取对应的依赖类在容器中的实例,如果是@Value
则会从application.properties
中解析对应的值并通过ConversionService转换成对应的格式。
在完成依赖注入(populateBean
)后,会调用initializeBean
进行初始化。内部通过applyBeanPostProcessorBeforeInitialization
完成前置处理,通过invokeInitMethod
完成@Bean
中initMethod= xxx()
方法的调用,applyBeanPostProcessorAfterInitialization
完成后置处理。
这样一个Bean就创建并初始化完成。
通过addSingleton
将这个单例Bean放入DefaultSingletonBeanRegistry
的singletonObjects
这个ConcurrentHashMap
中。