xml解析:
- XmlBeanFactory继承自DefaultListableBeanFactory,XmlBeanFactory使用XmlBeanDefinitionReader的loadBeanDefinitions方法将xml的Resource资源进行解析和读取。
- XmlBeanDefinitionReader将xml资源委托给DefaultDocumentLoader类的loadDocument方法将xml的Resource转换为Document资源返回给XmlBeanDefinitionReader,XmlBeanDefinitionReader调用registerBeanDefinitions方法将Document资源委托给DefaultBeanDefinitionDocumentReader,DefaultBeanDefinitionDocumentReader调用parseBeanDefinitions方法对Document资源的各个节点 进行解析并注册。
- 注册主要是DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法中调用了BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法对Document的节点解析成BeanDefinitionHolder,BeanDefinitionHolder中封装了beanName、BeanDefinition、Aliases等属性。
- 然后调用DefaultListableBeanFactory核心类的registerBeanDefinition(beanName, definitionHolder.getBeanDefinition())方法完成BeanDefinition的向ioc容器注册,ioc容器就是以DefaultListableBeanFactory内部的一个ConcurrentHashMap作为存储存储媒介
单例bean的加载创建:
AbstractBeanFactory类getBean方法中的doGetBean这个方法蕴含了整个bean的依赖注入、bean的创建、属性赋值、初始化、后置处理器的前后置方法的调用、循环依赖解决等。
doGetBean方法主要有两个分支,分支一:从缓存取bean,分支二:缓存中不存在bean,从头开始创建bean
从缓存取bean
- doGetBean中先通过getSingleton(beanName)获取缓存中的对应beanName的原始对象,然后调用getObjectForBeanInstance方法对应原始对象进行还原,创建出来的bean都要经过getObjectForBeanInstance方法才能完成创建,原因是创建出来的bean可能是一个factorybean工厂对象,所以需要调用此方法,内部会判断如果是一个factorybean,就会调用其getObject方法还原bean,还原后直接返回
- 为解决单例模式的循环依赖,在spring创建bean的时候是不等bean创建完成就将创建的objectFactory提前曝光加入缓存中,一旦下一个bean创建需要依赖上一个bean的时候则直接使用objectFactory
getSingleton 方法涉及了spring的三级缓存:
singletonObjects:第一级缓存,存放可用的完全初始化,成品的Bean。存放的是beanName与bean实例
earlySingletonObjects:第二级缓存,存放半成品的Bean,半成品的Bean是已实例化好的对象,但是未注入属性和初始化,这个bean对象有可能是个AOP代理的bean。用来处理被AOP代理后的bean的循环依赖问题,这里主要是存放的是beanName与正在创建的bean实例,这个bean有可能是已经创建好的代理的bean。如下面的代码,从三级缓存singletonFactories取出的singletonFactory.getObject()方法其实就是调用匿名函数的getEarlyBeanReference方法,这个方法内部会调用SmartInstantiationAwareBeanPostProcessor后置处理器的getEarlyBeanReference方法里的wrapIfNecessary方法生成代理。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
1、----------------------------------------------------缓存到二级缓存中-----------------------------------------------
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
2、--------------------------------------------------在调用createBeanInstance实例化bean后会保存bean到三级缓存中------------------------------------------------
addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
3、------------------------SmartInstantiationAwareBeanPostProcessor 后置处理器是AOP会调用AbstractAutoProxyCreator类的getEarlyBeanReference生成AOP的代理----------------------------
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
可以概括为二级缓存存放的就是那些从三级缓存中取出的objectFactory对象调用getObject()方法返回的对象,这个方法会调用到getEarlyBeanReference方法给那些aop注解对象生成代理,而且这个对象是已经完成实例化但是还未完成属性赋值或者初始化
singletonFactories:第三级缓存,存的是Bean工厂对象。用以解决循环依赖。如果Bean存在AOP的话,返回的是AOP的代理对象,并配合二级缓存解决循环依赖。存放的是beanName与objectFactory,这是解决循环依赖的主要手段。
从头开始创建bean
- 先判断是否是多例并且存在循环依赖,是则抛出异常,不处理
- 查找ioc容器中是否包含这个bean,不包含则需要从父类容器中getBean方法创建bean
- ioc容器中存在此beanName的BeanDefinition,则将此BeanDefinition及其父类的属性合并成RootBeanDefinition
- 使用RootBeanDefinition.getDependsOn()方法查找这个bean创建需要依赖的对象,先遍历这些属性调用getBean创建这些依赖对象
- 从RootBeanDefinition判断这个bean是单例还是多例,单例则使用,以下代码创建
//这个getSingleton和上面的getSingleton不一样,是个重载的getSingleton方法
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
这里的getSingleton主要是使用匿名函数createBean创建的objectFactory然后调用getObject完成bean的创建初始化,然后将创建好的bean实例singletonObjects一级缓存中, 然后调用getObjectForBeanInstance对原始对象进行还原
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
......................
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
if (beanInstance != null) {
return beanInstance;
}
}
......................
try {
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
......................
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
//判断后置处理器是否为InstantiationAwareBeanPostProcessor类
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
//前置处理,大多数aop代理从这里生成
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//后置处理
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
}
return bean;
}
- 在resolveBeforeInstantiation方法内,主要是使用InstantiationAwareBeanPostProcessor的前置处理方法postProcessBeforeInstantiation()进行代理对象的生成器AutoProxyCreator的创建,如果调用前置处理方法返回的对象不为空则继续调用后置处理方法postProcessAfterInitialization()
- 在createBean方法中如果resolveBeforeInstantiation方法返回的是空对象,那么就需要使用doCreateBean进行创建了,doCreateBean方法是蕴含了bean对象的实例化、属性赋值、实例化的一系列生命周期的方法,其中夹杂了许多前后置的处理调用,这个方法非常关键
单独分析doCreateBean方法
doCreateBean也是AbstractAutowireCapableBeanFactory的方法,是bean进行常规创建的方法。
- bean的实例化。先使用createBeanInstance方法进行bean的实例化,这是bean生命周期的第一个阶段,里面包含里多种实例化策略,包括了工厂方法、构造函数自动注入、简单初始化等,具体的逻辑是,如果BeanDefinition中包含工厂方法优先使用工厂方法实例化、否则spring会更加参数去锁定使用bean中的哪一个构造方法,如果不是工厂方法也不存在带参数的构造方法,则使用默认是无参构造进行实例化,实例化的bean是以BeanWrapper类型存在,BeanWrapper封装了bean各类消息,通过BeanWrapper.getWrappedInstance返回实例化的bean。
- 调用完createBeanInstance实例化完bean后,然后spring为了解决循环依赖,会在完成bean创建前调用addSingletonFactory方法,将objectFactory放入三级缓存中,以此解决循环依赖。objectFactory是通过实例化的bean实例去生成的。
- 这里我们单独说一下spring如何解决循环依赖,spring调用了我们刚刚提到的addSingletonFactory方法,代码如下:
//mbd是RootBeanDefinition,bean是BeanWrapper调用getWrappedInstance()返回的刚刚实例化的bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
我们在看看里面的匿名函数:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
}
}
return exposedObject;
}
这里使用了SmartInstantiationAwareBeanPostProcessor的后置处理器的调用,对bean进行处理,aop将advice动态织入也是在这里实现的,也就是基于SmartInstantiationAwareBeanPostProcessor类实现的动态织入,spring如何使用其解决循环依赖依赖的呢?假如此时A创建时需要创建B,B创建时需要A,而此时通过提供objectFactory来填充B的依赖属性A,因为A是正在创建进行中,只进行了实例化,没有进行任何的属性赋值,但是objectFactory就是在此方法中通过刚刚实例化的A的实例bean生成的,所以此objectFactory指向的属性地址是与B中持有的A是一样的,B也只是仅仅需要A类型的属性赋值以便完成创建而已,所以A能填充到B中,这样就解决了循环依赖。这仅仅只是getset方法注入及单例才能解决的循环依赖。如果是构造器注入的话是没有办法解决循环依赖的,原因是A构造器注入时需要一个创建好的B,B构造器注入时需要一个创建好的A,因此A和B没办法实例化,提供一个A或者B属性的对象,这样就没有办法解决循环依赖。但是getset注入就可以使用无参构造一个bean,所以能做到完成属性赋值等一系列操作前暴露一个使用构造好的bean创建的objectFactory去解决循环依赖,并不需要完成创建好。多例模式无法解决循环依赖的是因为bean每次使用时都需要创建一个最新的对象,对象没办法进行复用所以容器不会进行缓存,就无法提前暴露一个bean。
当面试官提问spring如何解决循环依赖时可以这么会答:在单例模式getset注入的情况下,spring的创建bean的过程中,bean进行实例化后会暴露一个objectFactory并存入三级缓存中,在还没有完成bean的创建完成前会使用三级缓存解决循环依赖的问题,如果是AOP代理对象产生的循环依赖会使用二级缓存和三级缓存共同处理,完成bean的创建后就会将对应的二级缓存和三级缓存移除,并存入一级缓存,以便下次使用时可以复用
bean的属性赋值:回到doCreateBean方法调用完addSingletonFactory方法之后会使用populateBean方法对bean进行属性赋值,这是bean生命周期的第二个阶段,详细过程是从RootBeanDefinition获取PropertyValues对象,根据条件决定调用autowireByName方法按名称调用还是autowireByType按类型注入,无论是按名称注入还是按类型注入都是根据RootBeanDefinition和BeanWrapper去查找需要注入的依赖bean,然后对这些bean进行循环遍历并调用getBean方法一一创建依赖对象,将依赖对象存储到PropertyValues中,变量后置处理器对PropertyValues中的依赖属性进行后置处理,然后调用applyPropertyValues方法将PropertyValues设置的依赖对象应用到已经实例化好的bean到中,这样就完成了bean的属性赋值
bean的初始化(AOP产生的重要阶段):bean的后置处理器BeanPostProcessor就是在bean的初始化前后执行的,AOP也是在这个初始化之前进行创建,回到doCreateBean方法继续调用initializeBean去完成bean生命周期的第三个阶段初始化,此时bean已经完成了实例化以及属性赋值,这时就会调用用户设定的初始化方法。方法中调用invokeAwareMethods这个方法会调用一系列的xxxxAware类的方法,这里AOP的创建类autoProxyCreator也是继承了Aware类,所以也会调用相应的setFactory方法初始化工厂类。然后执行BeanPostProcessor的前后置处理方法,applyBeanPostProcessorsBeforeInitialization是遍历postPostProcessor的前置方法,在bean初始化完成后在执行applyBeanPostProcessorsAfterInitialization遍历postPostProcessor的后置方法并调用,autoProxyCreator也是继承了BeanPostProcessor类,所以AOP会在这里创建代理对象,也就是说AOP代理对象的创建时机就是在bean的初始化后BeanPostProcessor的后置方法中
初始化完成后返回实例对象,然后返回到doGetBean方法中,将其传入getObjectForBeanInstance方法将bean进行还原,然后返回
Spring几个重要的拓展点
后置处理器PostProcessor
本身也是一种需要注册到容器里的Bean
◆其里面的方法会在特定的时机被容器调用
◆实现不改变容器或者Bean核心逻辑的情况 下对Bean进行扩展
◆对Bean进行包装,影响其行为、修改Bean的内容等
InstantiationAwareBeanPostProcessor和BeanPostProcessor、BeanDefinitionRegistryPostProcessor
@Component
public class Inintion implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class> beanClass, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor:postProcessBeforeInstantiation");
System.out.println(beanName+"开始实例化");
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor:postProcessAfterInstantiation");
System.out.println(beanName+"实例化完成");
return false;
}
}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName+"开始初始化了.......");
System.out.println("BeanPostProcessor:postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(beanName+"初始化完成了.......");
System.out.println("BeanPostProcessor:postProcessAfterInitialization");
return bean;
}
}
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition();
rootBeanDefinition.setBeanClass(Hadoop.class);
registry.registerBeanDefinition("hadoop32", rootBeanDefinition);
System.out.println("BeanDefinitionRegistryPostProcessor:postProcessBeanDefinitionRegistry===============");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanDefinitionRegistryPostProcessor:postProcessBeanFactory===============");
}
}
加载bean观察现象
@Data
@Component
public class Html {
private Integer id;
private String name;
public Html(Integer id, String name) {
this.id = id;
this.name = name;
}
public Html() {
System.out.println("html调用了构造方法");
}
//@PostConstruct在容器的组件初始化后使用
@PostConstruct
public void post() {
System.out.println("Html调用了@PostConstruct的方法");
}
//@PreDestroy在容器的组件被摧毁前被调用
@PreDestroy
public void destroy() {
System.out.println("Html调用了@PreDestroy的方法");
}
}
结论:
1、InstantiationAwareBeanPostProcessor是在bean实例化前后调用,postProcessBeforeInstantiation是在实例化前执行,返回值不为null时,就会接着调用postProcessAfterInstantiation。postProcessAfterInstantiation也会在实属性赋值前,实例化后再次执行
2、BeanPostProcessor是在bean初始化前后调用的,postProcessBeforeInitialization是在bean初始化前执行,postProcessAfterInitialization是在bean初始化后执行,其中大多数代理对象就是在这里产生的
3、BeanDefinitionRegistryPostProcessor是在bean的注册前后调用
初始化InitializingBean
spring初始化bean有两种方式:
- 第一:实现InitializingBean接口,继而实现afterPropertiesSet的方法
@Component
class MyInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean:afterPropertiesSet===============================");
}
}
- 第二:反射原理,配置文件使用init-method标签直接注入bean