上一节分析了Spring如何读取xml配置文件并最终将配置的POJO类生成一个个BeanDefinition
注册到IOC容器的过程,主要是针对直接配置在xml中的标签来分析的,应该来讲生成BeanDefinition指数读取配置放入到指定属性中,并非太难理解。 IOC的第二步是经过getBean()
获取一个bean实例,相对而言,建立一个bean比生成一个BeanDefinition
热闹多了,bean的singleton和prototype模式,bean的属性注入,bean的循环依赖,bean方法拦截等等都是建立一个bean要解决的问题,而这一些对于使用者来讲无需关注,但若是能了解Spring的实现原理,遇到问题才不会手忙脚乱。java
BeanFactory
是Spring提供给咱们用于获取bean实例的接口,这个接口很简单,没有多余的方法,只有一个很是核心的getBean(),经过该方法就能够获取一个bean的实例。在Spring中该接口是由DefaultListableBeanFactory
实现,真正的业务处理在AbstractBeanFactory
类里面,再来回忆下这张类图:算法
getBean
的入口在DefaultListableBeanFactory
,准确来讲是在AbstractBeanFactory
这个类里面,由于getBean()的不少实现都是在AbstractBeanFactory
这个抽象类里面。spring
再来看一下测试案例:数组
@Test
public void testSpringLoad() {
ClassPathXmlApplicationContext application = new ClassPathXmlApplicationContext("spring/spring-context.xml");
Person person= (Person) application.getBean("person");
BeanService beanService= (BeanService) application.getBean("beanService");
System.out.println(beanService);
System.out.println(person);
}
复制代码
在这个测试案例里,须要经过application获取到一个person和beanService的实例,这个实例在xml的配置信息以下:缓存
<!--setter注入-->
<bean id="beanService" class="com.yms.manager.model.BeanService">
<property name="mapper" ref="userDao"/>
<property name="name" value="lijinpeng"/>
<property name="sex" value="false"/>
</bean>
<!--构造器注入-->
<bean id="person" class="com.yms.manager.model.Person">
<constructor-arg name="age" value="26"/>
<constructor-arg name="name" value="dangwendi"/>
<constructor-arg name="userDao" ref="userDao"/>
<constructor-arg name="sex" value="true"/>
</bean>
<bean id="userDao" class="com.yms.manager.model.UserDao"/>
复制代码
经过这些配置,须要获得预期的结果:安全
这两种方式实际上对应了setter注入和构造器注入,因为getBean()里面的实现很是复杂,针对注解和aop使用了几个BeanPostProcessor
在bean的不一样生命周期执行注入,里面用的类不少,若是把全部的状况都分析下来,估计很快就懵了,因此仍是经过这个简单的案例来分析一下Spring是如何实例化bean的,在分析原理时相对而言容易理解一点。app
BeanFactory里面经过getBean获取bean实例,先来看一下getBean的几个重载:ide
getBean(String name)
函数
getBean(Class<T> requiredType)
post
getBean(String name, Class<T> requiredType)
getBean(String name, Object... args)
这四个重载方法都用于获取bean实例,经过参数名就能够看出,name就是bean实例化时候的beanId,这个id的值若是经过xml配置就是bean的name属性,若是是注解就是自动生成的,默认是类名的首字母小写。requiredType是须要获取指定Class的bean,这里重点了解一下最后一个重载,这个方法第二个参数是一个动态数组,这个动态数组主要用于指定建立bean实例时候要使用的构造函数的参数列表或者建立bean的工厂方法返回bean的方法参数列表,这也就意味着,咱们能够在使用的bean的时候能够经过指定不通的构造参数获取bean的不一样对象,经常使用于工厂模式。
在看源码之前,首先来想一下若是本身简单实现,应该如何获取一个bean,前面说过IOC实际上就是一个线程安全的hashMap,准确来讲是 ConcurrentHashMap<String, Object>
,知道这个那就简单了,因此大概应该是这个步骤:
经过beanName去第一步生成的BeanDefinitions查找BeanDefinition
从BeanDefinition
获取className,匹配一个合适的构造函数,经过反射获取一个实例对象
从BeanDefinition
获取配置的属性值,经过反射注入到实例对象中
返回bean实例
上面的分析步骤是针对getBean(String name) 这个重载方法的,若是是getBean(Class<T> requiredType)
则在第二步须要变更一下:
BeanDefinition
提供一个方法resolveBeanClass
将配置className解析成beanClass对象,而后从BeanDefinitions查找beanClass为requiredType的对象返回实例。而后进行三、4步骤便可。
Spring的实现方式实际上复杂得多,简单来讲Spring是这么处理得:
先从缓存中查找是否已经存在解析过的名为name,若是有,直接返回
若是bean是FactoryBean
或者是bean工厂类,调用getObject()或者工厂方法获取bean实例
匹配合适的构造函数,经过反射建立一个bean的实例
经过ObjectFactory
提早暴露bean,解决循环依赖的问题
调用populateBean
方法完成bean的属性注入
将实例化完成的bean放入到IOC容器中
spring中bean的获取,针对注解注入和AOP的入口都是在实现了BeanPostProcessor
的类里实现的,这些类共同组成了bean实例化过程当中的一部分生命周期,经过上面对getBean的简要分析,接下来就去看看Spring的源码部分吧。
上面说过,AbstractBeanFactory
是建立bean实例的程序入口,具体到方法是doGetBean
,因为这个方法比较长,这里只分析比较重要的逻辑,下面的方法比源码有些精简,不过核心业务都是有的:
protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly){
//解析bean的真正name,若是bean是工厂类,name前缀会加&,须要去掉
final String beanName = transformedBeanName(name);
//核心1:从单例容器中获取缓存的bean
Object sharedInstance = getSingleton(beanName);
//若是从单例容器中到缓存的bean并且构造函数参数列表为空
if (sharedInstance != null && args == null)
{
//核心2:直接获取实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else{
//验证当前bean实例是否正在建立中,若是是 直接抛出异常
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//中间省略了经过工厂方式建立bean的代码
.............
if (!typeCheckOnly)
{
//核心3:将当前bean实例放入alreadyCreated集合里,标识这个bean准备建立了
markBeanAsCreated(beanName);
}
try{
//从BeanDefinitions中获取该实例的BeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查要建立的实例bean的修饰符,是否容许被实例化
checkMergedBeanDefinition(mbd, beanName, args);
//省略了实例化bean的全部依赖bean的过程,建立过程是同样的
.............
// Create bean instance.
if (mbd.isSingleton()) {
//核心4:建立单例bean
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
//为了解决循环依赖,spring将使用ObjectFactory表示bean,提早暴露bean
//当真正属性注入的时候,调用ObjectFactory的getObject()方法获取bean实例
@Override
public Object getObject() throws BeansException {
try {
//核心5:真正建立bean的方法,重点要看的方法
return createBean(beanName, mbd, args);
}catch (BeansException ex) {
//若是建立bean异常 作一些清除工做
//包括将bean从alreadyCreated,singletonsCurrentlyInCreation等容器中清除
destroySingleton(beanName);
throw ex;
}}});
//获取真正的bean,因为bean能够经过FactortBean或者工厂bean的方式建立
//因此这个方法用于从Factorybean或者工厂bean获取要建立的真正的bean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
//省略 原型模式的建立
.............
}else
{
//省略scope做用于的建立
.............
}
}catch(BeansException ex){
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
//若是requiredType不为空,尝试将获取的bean转换成requiredType
.............
}
}
复制代码
spring源码里面这段代码其实特别长,若是都搬下来,恐怕逻辑并不会这么清晰,这里主要分析主上上的核心方法,这些方法里面涵括了实例化一个bean的全部操做。
首先分析这个方法的几个参数:
name:顾名思义就是bean的name
requiredType:bean对象的类型
args:建立bean实例构造函数所须要的参数列表,对应getBean
第四个重载方法
typeCheckOnly:bean实例是否包含一个类型检查
从当前案例来看,咱们只使用了name属性,剩下的三个参数都是默认值,其中requiredType和args都是null,typeCheckOnly是false。从上面分析来看,实例化一个bean首先要获取构造函数进行初始化,而后设置属性值,咱们来看这样一个状况,若是A中有一个属性为B b,B中也有一个属性A a,当实例化bean设置属性的属性,A会查找B的实例注入给属性b,若是B不存在会去建立B实例,当B实例设置属性a的时候回去查找A的实例,若是不存在则会建立A的实例,这个时候就会致使循环依赖的问题,Spring解决循环依赖是经过ObjectFactory
做为中间对象提早暴露实例解决的。而且将这些提早暴露的实例放入到earlySingletonObjects中,当须要真正使用bean实例时,就会调用ObjectFactory
的getObject
获取,固然Spring只是经过这种方式解决了单例模式下的循环依赖问题,了解了这点下面看getBean也许会容易点。
梳理一下这个方法所干的事情:
获取真正的beanName,说白了就是将FactoryBean
或者bean工厂类前面的&去掉
从单例容器中查找bean的缓存
若是缓存中存在,并且bean构造函数没有任何参数,直接建立bean实例返回
若是缓存不存在,将当前bean标记为建立状态,开始建立bean实例
从BeanDefinitions中查找bean声明,经过BeanDefinition建立bean返回
若是requiredType不为空,还须要将上面步骤生成的bean转换成requiredType返回
接下里就看看各个方法所做的事情吧,首先看getSingleton(beanName)
,直接定位到关键的方法实现:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从单例的IOC也就是hashMap中获取是否已经存在bean实例
Object singletonObject = this.singletonObjects.get(beanName);
//若是缓存不存在&&当前正常建立的单例对象就是该bean实例就进入建立方法
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//为了线程安全将单例的IOC容器锁起来
synchronized (this.singletonObjects) {
//从提早暴露容器中查找是否存在对应的ObjectFactory
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
//若是仍是找不到就从bean工厂类的缓存中查找
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//若是存在建立该实例的bean的工厂类 则经过工厂类建立bean
singletonObject = singletonFactory.getObject();
//将建立的bean放入到提早暴露容器集合里
this.earlySingletonObjects.put(beanName, singletonObject);
//由于已经存在了实例无需再经过工厂建立,
//将建立该实例的工厂从工厂让其中删除
this.singletonFactories.remove(beanName);
}
}
}
}
//返回从缓存中获取结果
return (singletonObject != hNULL_OBJECT ? singletonObject : null);
}
复制代码
这个方法的目的就是从单例缓存中获取bean的实例,首先从单例容器中获取,若是获取不到,再到提早暴露的容器里去查找,这个容器是earlySingletonObjects
,也是一个ConcurrentHashMap,这个容器存在的意义就是为了解决循环依赖,因此将bean转换成ObjectFactory
提早放入到容器中暴露出去,若是这个还找不到,就去建立bean的工厂类里面去查找,什么是bean的工厂类呢,看下这段配置就明了了:
<bean id="bankPayService" class="com.yms.manager.serviceImpl.BankPayServiceImplFactory" factory-method="getService"/>
复制代码
bean的获取是经过BankPayServiceImplFactory
的getService
方法获取的,BankPayServiceImplFactory
就叫作bean的工厂类,毫无疑问,若是是第一次使用bean实例,经过这个方法什么也获取不到,最终返回一个null,当在第二次使用bean实例的时候,直接执行到这里其实能够获取到第一次加载的bean的,对单例做用域的bean来讲,无需再次实例化bean,极大的提升了spring的性能,这也是这一步为什么如此关键的缘由。
上面说了,若是是第一次获取某个bean实例,不管如何也没法从缓存中获取到bean的实例,但鉴于代码执行顺序缘由,仍是先把获取缓存的bean的状况分析下去,假如spring经过缓存拿到了bean实例对象,并不会直接返回对象,还须要执行方法 getObjectForBeanInstance
:
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {
// 若是bean实例不是FactoryBean 但name又是工厂的前缀引用&,直接抛异常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
//若是beanInstance可能FactoryBean也多是普通的bean
//若是beanInstance是普通的bean或者仅仅是一个工厂实例 直接返回
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
//若是BeanDefinition为null,则从factoryBeanObjectCache查找实例
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
//通过上面判断已经肯定beanInstance是FactoryBean
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// 若是bean是一个FactoryBean则缓存起来
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
//这个就复杂了,主要用于当BeanDefinition的属性值
//又是一个BeanDefinition的时候的解析赋值,后面aop还会分析
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
复制代码
这个方法主要是获取真正的beanInstance,当从缓存里获取的bean实例是一个普通的bean或者是工厂bean的时候,直接返回,但若是是FactroyBean
并且属性值又是一个BeanDefinition
,便是一个合成bean的时候,须要调BeanPostProcessor
的实现类去解析BeanDefinition
最终生成一个bean实例,合成bean在AOP里面很常见,分析AOP的时候会详细说明,看到这里,其实就已经获取到了缓存中的bean实例对象了,不用过度关心最后一个方法,里面无非也就是将eanDefinition
的属性值转换成bean实例的过程。
通过上面两个方法,Spring已经能够从缓存中获取一个Bean的实例了,可是当第一次获取bean的时候,又该怎么处理呢,继续往下看,首先看一个if语句里面的方法isPrototypeCurrentlyInCreation
:
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
复制代码
这个方法很简单,就是在建立原型做用域的bean时首先去prototypesCurrentlyInCreation
容器中检查是否存在beanName的bean正在建立,若是存在就抛出异常,prototypesCurrentlyInCreation
这个集合每一个线程都会保存一份,因此这里判断的是当前线程中名为beanName的bean是否正在建立,由于Spring只经过提早暴露的方式解决了单例bean的循环依赖,对于Prototype模式的bean只要当前线程中存在其余正在建立的相同的bean,就直接抛出异常,单例bean的建立只有一个线程,因此也能够用这段代码去校验,看一下prototypesCurrentlyInCreation的定义就清晰了。
ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<Object>("Prototype beans currently in creation");
复制代码
ThreadLocal
会为每一个线程生成一个prototypesCurrentlyInCreation
集合,多个线程之间不受影响。
校验完bean的循环依赖后,还须要将bean标记成已经建立状态,标志着这bean已经被建立过,下次再来获取的时候,无需再次建立:
protected void markBeanAsCreated(String beanName) {
//alreadyCreated也是一个hashMap
this.alreadyCreated.add(beanName);
}
复制代码
此时bean实例建立的环境条件都已知足,能够开始建立bean了,首先须要根据beanName获取到BeanDefinition
,下面的方法做用是获取到BeanDefinition
,并将BeanDefinition转换为RootBeanDefinition:
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
//从mergedBeanDefinitions查找,该map里面存储的都是RootBeanDefinition
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null) {
return mbd;
}
//若是根据beanName查询不到RootBeanDefinition,则转换成RootBeanDefinition
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
复制代码
这个时候就用到了IOC第一个大步骤中生成的BeanDefinition了,在上一篇中说了BeanDefinition
里面主要存储了bean的类的全部信息,包括类的元素和属性信息,接下来就是解析BeanDefinition
里面的数据,往bean实例里面填充就能够了,可是首先须要获取一个初始化后的bean实例,此时的bean应该仅仅是一个空的对象,属性什么的都没有赋值。由于是针对单例的bean分析的,接下来调用getSingleton
方法,这个方法第一个参数是beanName,第二个是一个匿名内部类,bean对象实际就是由匿名内部类的实现方法createBean建立的:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
//再次尝试从单例容器中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//判断单例IOC容器是否已经被销毁
if (this.singletonsCurrentlyInDestruction) {
//若是单例IOC容器都被销毁了 就直接终止bean的建立
throw new BeanCreationNotAllowedException(beanName,"不能再已经销毁的容器中建立bean");
}
//建立前检查 bean初始化的前置操做能够被覆盖,
//默认检查当前bean是否正在建立的bena的容器中
beforeSingletonCreation(beanName);
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
//核心方法最终会调用到上一个方法的匿名内部类的getObject
singletonObject = singletonFactory.getObject();
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
//将建立的bean放入到单例IOC容器中
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
复制代码
这个方法首先是校验了单例IOC容器是否处于存活状态,若是已经被销毁直接抛出异常,不容许建立该bean,而后校验了当前bean是否已经放入到了正在建立的bean的集合中,也就是是否容许被建立,若是当前bean处于被容许被建立的集合中,调用参数ObjectFactory
的getBean()方法获取bean对象,参数singletonFactory
是一个匿名内部类,最终会执行核心方法5:createBean(beanName, mbd, args)
这个方法去建立bean,等会就会看哪一个方法,如今加入已经经过getBean获取到了bean实例对象,而后调用addSingleton(beanName, singletonObject)
;将当前bean注册到单例IOC容器中。
截止到如今,终于能够看看建立一个bean的最核心的方法createBean(beanName, mbd, args)
了,首先看看这个方法的参数,beanName是要获取bean的name,mbd是bean的BeanDefinition对象,args是动态指定的构造函数的参数集合,固然在这个测试案例里,args是null。createBean是一个抽象方法,由类AbstractAutowireCapableBeanFactory
实现:
@Override
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){
//这一步主要是将配置得class转换成Class对象
resolveBeanClass(mbd, beanName);
try {
//解析lookup-method和replaced-method方法
mbd.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
//根据mbd校验是不是一个合成类,执行BeanPostProcessors处理器
//这里能够建立一个代理对象
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
//开始建立一个具体的,很单纯的bean,所谓单纯就是原生的bean
Object beanInstance = doCreateBean(beanName, mbd, args);
return beanInstance;
}
复制代码
这个方法里面其实也就是调用建立bean的方法,只不过在Spring里面建立bean有两种方式,一种就是原生bean的建立,另外一种就是代理bean的建立,基于代理bean的建立的入口是在 实现了BeanPostProcessor
的类中执行,这个在Spring AOP中会具体分析,这里针对测试案例而言时须要建立原生的bean,这样就进入到了doCreateBean
方法中:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
//初始化bean的bean最终被封装到这个类里
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
//由于是单例,须要从缓存中移除 以后再从新生成
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//这个方法会经过查找到的构造函数初始化一个纯净的属性未被赋值的bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
//容许修改BeanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
//校验bean是否使用了循环依赖
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//属性注入,为初始化的bean设置属性值
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//这个地方会检查bean是否实现了一些Aware方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
throw ex;
}
//解决循环依赖问题,若是有循环依赖,从新获取bean对象,只是参数为false
//表示再次获取时不容许有循环依赖问题,因为此时已经能够从缓存中获取到依赖的
//bean对象,而后经过getObject()获取便可
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
}
}
// 最后将生成的bean实例注入到单例IOC容器中
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
复制代码
这个方法真正完成了生成bean的操做,代码和复杂,可是最终完成了如下三件事情:
createBeanInstance
匹配一个合适的构造函数,经过反射建立一个bean的实例,此时的bean属性并未赋值
populateBean
是为生成的初始化bean设置属性值,用于setter注入,initializeBean是method注入
通过上两步,bean已经被实例化了,可是若是有循环依赖问题,属性值只是一个ObjectFactroy
对象,并非一个真正对象,因此这个时候须要再次调用getSingleton
,从缓存中获取真正的bean。
就是这三个步骤最终完成生成bean的操做,前面看了这么多,其实都是铺垫,这三个步骤决定了建立bena的过程,跟着上面的总结,分别来看看这三步操做时如何执行的。
若是bean有默认的无参构造函数,能够直接经过反射初始化一个bean对象,可是若是须要使用指定的构造函数初始化一个bean,就须要去查找合适的构造函数,而后完成初始化。Spring在设置一个构造函数参数的时候,容许使用name,type,index表示一个参数,使用ref和value表示参数值,其中name和type能够一块儿使用,参数值ref和value只能存在一个,看下面的方法:
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
//将class转换成Class,其实上面已经转换过了,直接就会获取到,不会再次加载
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//若是Class不容许被实例化 直接抛出异常
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//若是配置了factory-method,则从factory-method方法中获取bean
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//标识bean是否被建立而且解析过
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
//获取beanClass的全部构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//查找合适的构造函数而后初始化bean
return autowireConstructor(beanName, mbd, ctors, args);
}
//直接使用默认无参构造函数初始化bean
return instantiateBean(beanName, mbd);
}
复制代码
其实createBeanInstance
并无完成初始化bean操做,仅仅是针对不一样状况,使用了不一样方式的初始化,好比若是bean配置了factory-method,就是使用配置的工厂方法去建立一个bean,若是beanClass构造函数列表不为空,则先去匹配到一个构造函数,再去初始化,若是beanClass有默认的无参构造函数,则直接进行初始化便可,这里来分析使用匹配的构造函数初始化bena的过程,测试案例中最终也会执行autowireConstructor(beanName, mbd, ctors, args)
:
protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
复制代码
从上面代码看来,初始化bean的操做被委托给了ConstructorResolver
的autowireConstructor
方法,说实话,这段代码实现太长了, 都写下来恐怕真的很复杂,分析以前仍是先简单的介绍下这个方法的做用:
根据参数个数以及参数的name,type或者index匹配一个构造函数 初始化bean,这里读取构造函数参数名是使用asm读取类的字节码文件获取到的。
获取参数的真实值,在生成BeanDefinition
时候,ref的值会被保存为RuntimeBeanReference
,value的值会被保存为TypedStringValue
,这里会根据不一样的类型值使用不一样的解析方式。
这里仍是精简后的代码,只分析核心部分:
public BeanWrapper autowireConstructor( final String beanName, final RootBeanDefinition mbd, Constructor[] chosenCtors, final Object[] explicitArgs) {
//省略代码....
//最终匹配到的要使用的构造函数
Constructor constructorToUse = null;
ArgumentsHolder argsHolderToUse = null;
//匹配到的构造函数所使用的参数列表
Object[] argsToUse = null;
//explicitArgs是在getBean(benaName,args)指定了构造函数参数列表
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
//若是未指定构造函数的参数列表,要根据配置文件去匹配合适的构造函数的参数列表
else
{
//尝试从缓存中获取
..........
}
//若是构造函数参数列表未指定 也没法从缓存中获取 读取配置文件配置
if (constructorToUse == null) {
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
int minNrOfArgs;
if (explicitArgs != null) {
minNrOfArgs = explicitArgs.length;
}
else {
//从BeanDefinition中获取 也就是从配置文件中获取
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
//因为构造函数参数可能须要转换成真实值,用这个类接收参数值
resolvedValues = new ConstructorArgumentValues();
//将参数值放入到ConstructorArgumentValues中并返回参数个数
//这个方法会将RuntimeBeanReference,TypedStringValue等中间值解析成真实值
//等会须要看这个方法
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
}
//若是指定了构造函数,则从指定的构造函数中查找合适的,这里为null
Constructor[] candidates = chosenCtors;
if (candidates == null)
{
Class beanClass = mbd.getBeanClass();
try {
//获取bean实例的全部构造函数
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
//bean不能被实例化 没法获取构造函数 抛出异常
throw ex;
}
}
//根据构造函数参数个数进行排序
AutowireUtils.sortConstructors(candidates);
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor> ambiguousConstructors = null;
List<Exception> causes = null;
//遍历bean的全部构造函数 最终找到一个合适的构造函数
for (int i = 0; i < candidates.length; i++) {
Constructor<?> candidate = candidates[i];
Class[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse.length > paramTypes.length) {
//由于前面已经对构造函数参数根据参数个数进行排序,因此若是当前的参数
//个数都不知足,后面的构造函数参数个数确定不知足 直接中断循环便可
break;
}
//若是
if (paramTypes.length < minNrOfArgs) {
continue;
}
ArgumentsHolder argsHolder;
//下面这个执行体里主要是经过asm获取构造函数的方法参数名
//根据参数名和参数类型去检索出一个合适的构造函数
if (resolvedValues != null) {
try {
String[] paramNames = null;
if (constructorPropertiesAnnotationAvailable) {
paramNames = ConstructorPropertiesChecker.evaluateAnnotation(candidate, paramTypes.length);
}
if (paramNames == null) {
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
paramNames = pnd.getParameterNames(candidate);
}
}
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);
}
catch (UnsatisfiedDependencyException ex) {
throw ex;
}
else {
//根据传入的参数列表 获取一个构造函数
if (paramTypes.length != explicitArgs.length) {
continue;
}
argsHolder = new ArgumentsHolder(explicitArgs);
}
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// 若是匹配到了就选择这个构造函数 并将参数值赋予到
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<Constructor>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
//省略一些代码......
Object beanInstance;
if (System.getSecurityManager() != null) {
.........
}
else {
//最终根据选择构造函数和参数列表 初始化一个bean实例
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
bw.setWrappedInstance(beanInstance);
return bw;
}
}
复制代码
这段代码很长,真想看明白仍是建议经过断点调试的方式一点一点看里面的内容,针对这里面的不少方法不在具体分析,这个代码其实就完成了一个功能,匹配构造函数,只不过这里分了三种状况,若是指定了构造参数explicitArgs
,则使用,若是未指定则从缓存中读取,若是还未读取到则从BeanDefinition获取,最终获取到要使用的构造函数参数,而后获取bean的全部构造函数,根据参数name和type去匹配一个构造函数,最终初始化一个bean。在建立BeanDefinition
的时候,属性值或者参数值是经过RuntimeBeanReference
等中间类表示的,在下面的方法里就会将这些中间类解析成真正的值:
public Object resolveValueIfNecessary(Object argName, Object value) {
// We must check each value to see whether it requires a runtime reference
// to another bean to be resolved.
if (value instanceof RuntimeBeanReference) {
RuntimeBeanReference ref = (RuntimeBeanReference) value;
return resolveReference(argName, ref);
}
else if (value instanceof RuntimeBeanNameReference) {
String refName = ((RuntimeBeanNameReference) value).getBeanName();
refName = String.valueOf(evaluate(refName));
if (!this.beanFactory.containsBean(refName)) {
throw new BeanDefinitionStoreException(
"Invalid bean name '" + refName + "' in bean reference for " + argName);
}
return refName;
}
else if (value instanceof BeanDefinitionHolder) {
// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
}
else if (value instanceof BeanDefinition) {
// Resolve plain BeanDefinition, without contained name: use dummy name.
BeanDefinition bd = (BeanDefinition) value;
return resolveInnerBean(argName, "(inner bean)", bd);
}
.........
}
复制代码
这个方法会将中间类最终转换成实际的值,这里面有不少类型,能够支持更复杂的BeanDefinition
参数的解析。
通过上面分析,Spring会为bean匹配一个构造函数,而后获得初始化后的bean,此时的bean只是一个很"单纯"的bean,所谓单纯也就是bean并无完成实例化操做,也就是没有把相关属性值注入到这个bean的属性中,下面的方法就是完成属性注入的,属性注入通常有两种方式,一种是经过name注入也就是autowireByName
,还有一种是根据类型注入,也就是autowireByType
。
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
PropertyValues pvs = mbd.getPropertyValues();
if (bw == null) {
if (!pvs.isEmpty()) {
//若是bw为空 并且mbd里面有配置的属性,表明初始化失败,直接抛出异常
}
else {
//初始化失败 没有要注入的属性 继续直接返回
return;
}
}
//执行 BeanPostProcessor 若是有的话,这个是在bean进行属性设置以前对bean注入
//好比经过注解的方式进行属性注入就是在这里完成的
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 经过属性name注入值
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 经过属性的classType为属性注入值
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//这部分也执行BeanPostProcessor
if (hasInstAwareBpps || needsDepCheck) {
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
//最终在这个方法里面完成属性的设置的
applyPropertyValues(beanName, mbd, bw, pvs);
}
复制代码
这个方法其实就是从BeanDefinition中获取配置的属性值,首先会经过BeanPostProcessor
实现的类解析经过注解设置的属性,而后再解析经过配置文件配置的属性,注入属性有两种方式autowireByName
和autowireByType
,这个过程其实就是将BeanDefinition
引用的中间值转换成真实值的过程,而后经过applyPropertyValues
使用真实值对初始化的bean进行实例化。思路其实很简单,spring将经过注解的方式注入属性的逻辑放入到了BeanPostProcessor
中,复杂的逻辑其实在BeanPostProcessor
中,哪一个实现比起分析的基于xml配置的实现,封装性要更强一点,可是最终达到的效果是同样的,理解了基于xml配置的属性注入方式,基于注解的配置只要耐心的看,也很容易理解,属性注入的代码其实没什么好分析的。主要看下autowireByType
和autowireByType
,这两个方法若是是基于xml的须要配置autowire
属性,分别对应byName和byType,可是仍是要对比看看spring是如何实现的,首先autowireByType
:
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//获取注解的全部属性name
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
//判断容器中是否包含name的实例
if (containsBean(propertyName)) {
//若是直接包含 直接获取该实例便可
Object bean = getBean(propertyName);
//将实例添加到bean的属性集合里 等到注入
pvs.add(propertyName, bean);
//因为建立当前bena的时候,属性实例也被附带建立了,因此要注册到IOC容器中
registerDependentBean(propertyName, beanName);
}
else {
//IOC容器中没有对应name的属性值
}
}
}
复制代码
基于name去获取bean实例从代码上看很是简单,仅仅是经过name从IOC中获取属性名为propertyName
的实例。若是赵傲则放入到bean实例的属性参数集合中,等到被注入便可。与autowireByType
相比,autowireByType
可就复杂多了,复杂的缘由就是要解析依赖项的过程。
protected void autowireByType( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
try {
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
//若是属性类型为object 直接忽略就行
if (!Object.class.equals(pd.getPropertyType())) {
//获取 setter 方法(write method)的参数信息,好比参数在参数列表中的
//位置,参数类型,以及该参数所归属的方法等信息
MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
//建立属性依赖描述对象 这里面包含了字段类型 字段名 已是否必输等信息
DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
//解析属性依赖。获取bean对象 这里面比较复杂 是主要查找过程
Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
if (autowiredArgument != null) {
pvs.add(propertyName, autowiredArgument);
}
for (String autowiredBeanName : autowiredBeanNames) {
registerDependentBean(autowiredBeanName, beanName);
}
autowiredBeanNames.clear();
}
}
catch (BeansException ex) {
throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
}
}
}
复制代码
如上所示,autowireByType
的代码自己并不复杂。和 autowireByName
同样,autowireByType
首先也是获取非简单类型属性的名称。而后再根据属性名获取属性描述符,并由属性描述符获取方法参数对象 MethodParameter
,随后再根据 MethodParameter
对象获取依赖描述符对象,在获取到依赖描述符对象后,再根据依赖描述符解析出合适的依赖。最后将解析出的结果存入属性列表 pvs 中便可,核心的解析依赖对象在方法resolveDependency
中,这里就不展开分析了,感兴趣的能够调试看下。
通过上面的分析,Spring经过autowireConstructor
方法完成bean的初始化,经过populateBean
完成bean的属性注入(实例化),这只是最基本的bean的建立过程,在Spring中还有一些与bean生命周期相关的Aware接口,以及实例化后调用init-method
指定的方法的过程,回头看下populateBean
以后的代码,这段代码在doCreateBean
中:
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
//这个方法会检查bean是否实现了Aware接口 是否指定了init-method方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
复制代码
查看initializeBean方法
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
//检查是否实现了Aware接口
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
//检查是否实现了Aware接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行BeanPostProcessor的postProcessBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//查找是否指定了init-method方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//执行BeanPostProcessor的postProcessAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
复制代码
在这个方法中,主要作的事情能够归纳为如下四步:
首先会调用invokeAwareMethods
检查bean是否实现了Aware接口,若是实现了就调用Aware接口,
调用applyBeanPostProcessorsBeforeInitialization
方法,这个方法也是在bean建立的生命周期中,是bean在属性填充完毕以后在bean初始化方法调用以前执行,其实是调用的BeanPostProcessor
的postProcessBeforeInitialization
方法
调用invokeInitMethods
去检查bean是否指定了init-method
方法,若是指定了就执行
调用applyBeanPostProcessorsAfterInitialization
,对应的是调用BeanPostProcessor
的postProcessAfterInitialization
方法
接下来主要看看invokeAwareMethods
和invokeInitMethods
这两个方法:
private void invokeAwareMethods(final String beanName, final Object bean) {
//检查bena是否实现了对应的Aware接口
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
复制代码
下面的方法是检查bean是否指定了init-method
方法
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
//判断bean的属性是否由BeanFactoryAware或者BeanFactory等建立
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
//调用bean的afterPropertiesSet再次解析bean的属性
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
//查看是否指定了init-method
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
//若是指定了就执行init-method方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
复制代码
前面已经简单说过Spring是如何解决循环依赖问题,因为上面主要是分析Spring源码的过程,可能说的不是那么清晰,我以为有必要将这部份内容单独拿出来讲一说。
通过前面的步骤,已经能够获取到一个通过初始化的bean实例,并且完成了bean的属性注入,可是前面还有一个问题没有解决,若是在单例IOC中有循环依赖,暂时是用ObjectFactory
中间类代替的,因此还要经过ObjectFactory
的getObject
方法获取真正的bean,此时全部的bean已经被建立完成,因此经过getBean
能够获取到真实的bean实例对象,再看看下面的代码,这段代码也是在doCreateBean
中:
//解决循环依赖问题,若是有循环依赖,从新获取bean对象,只是参数为false
//表示再次获取时不容许有循环依赖问题,因为此时已经能够从缓存中获取到依赖的
//bean对象,而后经过getObject()获取便可
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
}
}
复制代码
Spring解决循环依赖是经过ObjectFactory
中间类实现的,固然经过这个类只能解决单例IOC的属性循环依赖的问题,对于原型模式和构造器的循环以来,spring至今也没有解决方法,首先来回顾一下Spring获取一个bean的简单过程:
singletonObjects
获取,也就是单例IOC容器中earlySingletonObjects
中获取,也就是经过ObjectFactory
实现的提早曝光的容器singletonFactories
获取,也就是实例化bean的实例工厂 从缓存中获取的bean的过程,网上不少都叫三级缓存,前面三个步骤对应了1,2,3级缓存。接下来举一个案例分析这个过程,假若有bean的依赖关系为:A->B->C->A,固然这些都是基于属性依赖的,当A执行到populateBean
方法实现属性注入的时候,会先去获取B实例,而后B执行populateBean
会获取C实例,C执行到populateBean
获取查找A实例,此时A实例正在被建立,又会循环上述过程,产生了循环依赖问题。Spring获取getBean()
最终调用下面简化后的方法:
protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
//关注点1
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
try {
if (mbd.isSingleton()) {
//关注点2
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
..............
}
return (T) bean;
}
复制代码
当A去查找bean的实例的时候,会调用上面的doGetBean
方法获取,这个方法里面有两个关注点,分别是两个重载方法getSingleton
,首先当A执行populateBean
查找B的实例时调用第一个重载:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//从三级缓存中获取
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
复制代码
这个方法是从三级缓存中查找bean,第一级缓存singletonObjects
里面放置的是实例化好的单例对象。第二级earlySingletonObjects
里面存放的是提早曝光的单例对象(没有彻底装配好)。第三级singletonFactories
里面存放的是要被实例化的对象的对象工厂,因为B第一次获取尚未被建立,因此一级缓存singletonObjects
获取结果确定为null,再看看看看进入二级缓存中的条件isSingletonCurrentlyInCreation(beanName)
:
public boolean isSingletonCurrentlyInCreation(String beanName) {
//在这里表示bean是否正在建立的过程,此时B 还没有在建立中,因此会返回false
return this.singletonsCurrentlyInCreation.contains(beanName);
}
复制代码
上面的步骤中并无任何操做往isSingletonCurrentlyInCreation
中加入B的beanName的操做,因此压根不会进入二级缓存,直接就返回null了,而后就判断bean是否时单例的,若是时调用getSingleton(String beanName, ObjectFactory objectFactory)
,此时objectFactory时一个匿名内部类,实例B的获取是经过内部类的createBean
获取的,这个是咱们关注点2 :
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
//从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,"不能从销毁的bean中建立");
}
//在这里将B的beanName添加到isSingletonCurrentlyInCreation
beforeSingletonCreation(beanName);
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<Exception>();
}
try {
//最终调用匿名内部类建立bean
singletonObject = singletonFactory.getObject();
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
复制代码
这个方法首先会从一级缓存中查找B,很明显,查到的结果为null,而后调用beforeSingletonCreation(beanName)
,将B的beanName添加到singletonsCurrentlyInCreation
中,也就是关注点1中没法进入二级缓存的那个集合校验:
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) &&
!this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
复制代码
紧接着就会调用singletonFactory.getObject()
建立名,也就是经过匿名内部类的createBean
方法建立,前面分析过,建立bean最终会调用doCreateBean
方法,这个方法简化了, 只看最核心的关注点3:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
...........代码省略...........
//关注点3
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
//初始化和实例化bean
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
catch (Throwable ex) {
throw ex;
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
}
}
}
...........代码省略...........
return exposedObject;
}
复制代码
createBeanInstance
利用反射建立了对象,下面咱们看看关注点3earlySingletonExposure
属性值的判断,其中有一个判断点就是isSingletonCurrentlyInCreation(beanName)
public boolean isSingletonCurrentlyInCreation(String beanName) {
return this.singletonsCurrentlyInCreation.contains(beanName);
}
复制代码
发现使用的是singletonsCurrentlyInCreation
这个集合,在上面的步骤中将的B的BeanName已经填充进去了,因此能够查到,并且在初始化bean的时候,还会判断检查bean是否有循环依赖,并且是否容许循环依赖,这里的ABC造成了循环依赖,因此最终earlySingletonExposure
结合其余的条件综合判断为true,进行下面的流程addSingletonFactory
,这里是为这个Bean添加ObjectFactory
,这个BeanName(A)
对应的对象工厂,他的getObject
方法的实现是经过getEarlyBeanReference
这个方法实现的。首先咱们看下addSingletonFactory
的实现
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
复制代码
往三级缓存singletonFactories
存放数据,清除二级缓存中beanName对应的数据。这里有个很重要的点,是往三级缓存里面存入了值,这是Spring处理循环依赖的核心点。getEarlyBeanReference
这个方法是getObject
的实现,能够简单认为是返回了一个为填充完毕的A的对象实例。设置完三级缓存后,就开始了填充A对象属性的过程。
上面理清以后总体来分析如下ABC的初始化流程,当设置A的属性时,发现须要B类型的Bean,因而继续调用getBean
方法建立,此次的流程和上面A的彻底一致,而后到了填充C类型的Bean的过程,一样的调用getBean(C)来执行,一样到了填充属性A的时候,调用了getBean(A),咱们从这里继续说,调用了doGetBean中的`Object sharedInstance = getSingleton(beanName),仍是关注点1的代码,可是处理逻辑彻底不同了。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中获取 此时二级缓存中应该也获取不到
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//从三级缓存中获取 此时能够获取到 A 的实例,虽然属性并不太完整
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
复制代码
仍是从singletonObjects获取对象获取不到,由于A是在singletonsCurrentlyInCreation
这个Set中,因此进入了下面的逻辑,从二级缓存earlySingletonObjects
中取,仍是没有查到,而后从三级缓存singletonFactories
找到对应的对象工厂调用getObject
方法获取未彻底填充完毕的A的实例对象,而后删除三级缓存的数据,填充二级缓存的数据,返回这个对象A。C依赖A的实例填充完毕了,虽然这个A是不完整的。无论怎么样C式填充完了,就能够将C放到一级缓存singletonObjects
同时清理二级和三级缓存的数据。一样的流程B依赖的C填充好了,B也就填充好了,同理A依赖的B填充好了,A也就填充好了。Spring就是经过这种方式来解决循环引用的。
经过上面的代码分析,Spring经过BeanFactory
的getBean()
方法获取bean实例的大体流程为:
从缓存中获取bean实例(三级缓存 解决循环依赖问题)
若是bean没有被建立过,执行建立bean的流程
autowireConstructor
匹配构造函数,经过反射建立一个bean实例
经过populateBean
完成bean的属性注入
经过initializeBean
检查bean配置得初始化方法和Aware接口
将建立得bean加入到IOC容器中
实际上,若是不考虑注解的话 ,Spring解析配置文件并完成bean的建立过程,就是上面的那部分代码,没有太多复杂的算法和抽象结构,很容易理解。Spring把不少解析注解的逻辑放入到了BeanPostProcessor
中执行并经过这些实现类控制了bean的生命周期,在每一个生成BeanDefinition或者getBean()的关键方法中,总会在方法前或后执行这些接口方法,这些接口最终会调用到封装好的功能,好比经过注解声明类和属性注入还有AOP的方法拦截。若是想了解这部分的实现,能够看下BeanPostProcessor接口的实现类,主要功能在那里封装的,内容比较抽象,但仍是很值得看的。到此为止,Spring IOC的原理基本上就分析完了,接下来会分析Spring AOP的部分。