这里只是做一部分笔记,用来配合看源码比较好
Spring要学习的点:
1.IOC
2.AOP
3.SpringMvc
4.设计模式
5.事务管理
先来看IOC
bean的生命周期:
- 实例化(getWrappedInstance())
- 注入属性(populateBean)
- 初始化(initializeBean)
- 销毁 (destory())
创建的这三个阶段是在具体beanFactory工厂类的doCreateBean里完成的
三级缓存:
-
一级缓存:singletonObjects,单例池,(内容:用于存放走完完整bean创建周期的bean)。
-
二级缓存:earlySingletonObjects ,当出现循环依赖的时候,即判断某个bean正在创建中的状态的时候,就会把这个bean往二级缓存里面存一份。(内容:没有经过初始化的原始对象或者代理对象)(如果需要AOP会提前进行AOP再将代理对象存进去)。
注入属性的时候会从单例池和二级缓存里面找。(作用:之所以需要二级缓存是因为在有多个属性循环依赖的时候,可能会产生多个代理对象,那么第一个产生的代理对象先放到二级缓存里面去的话,后面的先从二级缓存获取,获取不到才会再产生代理对象,这样就能保证始终都只有一个代理对象了) -
三级缓存:singletonFactories,存放一个getEarlyBeanReference的工厂。当一个单例bean实例化之后就调用addSingletonFactory方法会往里面存factory的lambda表达式。(作用:而这些信息之所以要在属性注入和初始化之前存进三级缓存,是因为如果要进行AOP的话,需要从三级缓存里面取出必要的信息来进行动态代理)
bean的循环依赖创建流程:(比如A依赖B,B依赖A)
一般进行AOP的时机是在属性注入以后,但是有循环依赖的话,这里A的AOP是在属性注入的时候创建的,所以A在属性注入之后判断如果已经AOP过了,就不会再AOP了。
A的流程:
- 通过扫描解析出beandefination,用于存在bean创建所需要的各种信息。
- 在CreatingSet中把bean名字加进去,表示这个bean正在创建中。
- 实例化bean,再接着给三级缓存存放该bean的工厂信息。
- 填充属性——》从单例池找该属性B的bean,没有的话就创建一个。
B的流程:
4.1. 实例化该属性B的bean对象——》给B填充属性A,在单例池和二级缓存找不到,又发现通过CreatingSet查到要填充的A正在被创建,那就是循环依赖了。这个时候会去判断A需不需要进行AOP,需要的话就在这里从三级缓存获取工厂信息,进行AOP,并把A产生的代理对象放入二级缓存。
4.2. 这时候就从二级缓存中找出刚第一个要创建的bean的对象。把它注入到第二个bean中去。
4.3. B进行AOP,再放入到单例池
A的流程:
- 接着A上面的操作,把B填充进去。
- 放入单例池
AOP
代理对象:代理对象中的属性值为空,它有一个target字段,而这个target存的是对原对象的引用,所有的属性赋值都在原对象中。(也就是bean的属性赋值阶段一直是对原始对象进行赋值的)
AOP最终进行动态代理的类是AbstractAutoProxyCreator这个类。
提前进行AOP调用的是getEarlyBeanReference,正常进行AOP是在postProcessAfterInitialization方法中。他们都是调用wrapIfNecessary来进行动态代理的。
提前进行AOP是在getSingleton里,如果一级二级缓存都获取不到,就会通过三级缓存进行AOP获取bean,并把结果放到二级缓存里,再删除三级缓存里的工厂,三级缓存中存储的getEarlyReference方法会进行AOP。
这是getEarlyBeanReference方法
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
//通过wrapIfNecessary返回代理对象
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
这是postProcessAfterInitialization方法
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//通过wrapIfNecessary返回代理对象
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
可以来看看wrapIfNecessary方法是如何生成代理对象的。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
//getAdvicesAndAdvisorsForBean会去获取所有可用的增强点
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//通过增强点来进行动态代理
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
- 通过getAdvicesAndAdvisorsForBean去获得增强点。
而getAdvicesAndAdvisorsForBean最终会通过buildAspectJAdvisors来找到所有带有@Aspect注解的增强点。 - 通过createProxy创建代理对象。
最终通过JdkDynamicAopProxy或者CglibAopProxy的getProxy来创建代理对象。
Spring的扩展点(所有的扩展点接口都实现了BeanPostProcessor)
影响多个bean的接口:
1.InstantiationAwareBeanPostProcessor接口
- resolveBeforeInstantiation调用点
调用时机:在实例化前调用
就是for循环调用所有的InstantiationAwareBeanPostProcessor接口 ,这个调用点在具体工厂类的createBean方法里调用(如AbstractAutowireCapableBeanFactory),并返回一个bean,如果为空则调用doCreateBean去创建bean。 - postProcessAfterInstantiation调用点
调用时机:在实例化后,属性赋值前调用,并且有一个返回值,来判断是否允许进行属性赋值
2.BeanPostProcessor接口
- postProcessBeforeInitialization调用点
调用时机:在初始化前,是一个beanPostProcessor - postProcessAfterInitialization调用点
调用时机:在初始化后,是一个beanPostProcessor
只有一个bean调用的接口:
3.Aware接口
-
第一组aware(BeanNameAware、2.BeanClassLoaderAware、BeanFactoryAware、)
在initializeBean的invokeAwareMethods直接调用以获取资源 -
第二组aware(EnvironmentAware、EmbeddedValueResolverAware、applicationContextAware)
在initializeBean的applyBeanPostProcessorsBeforeInitialization里调用
(@PostConstruct注解也是在applyBeanPostProcessorsBeforeInitialization里调用的) -
在initializeBean里还有一个
applyBeanPostProcessorsAfterInitialization,这是BeanPostProcessor的另一个调用点
生命周期相关的两个接口,这也只有实现他的bean才调用:
-
InitializingBean接口
调用时机:在initializeBean的invokeInitMethods方法里调用
由于aware方法都是执行在这个方法前面,所以可以在这个方法里去调用aware接口去获取资源,这也是我们自定义去扩展spring的常用方式。
自定义的方式:1.实现InitializingBean接口,2.xml里的init-method方法 -
DisableBean接口
调用时机:bean被销毁的时候调用
自定义方式:实现DisableBean接口