从 Spring IOC 容器中获取 bean 实例的流程:从context.getBean()方法开始
发生了循环依赖:
public class A {
@Autowired
private B b;
}
public class B {
@Autowired
private A a;
}
获取单例
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存(单例池)中查找对象
Object singletonObject = this.singletonObjects.get(beanName);
//单例池中找不到,而且被查找的bean正在创建中--发生了循环依赖
//通过singletonsCurrentlyInCreation(set)记录对象是否正在被创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
//从二级缓存中去寻找 原始对象或者是代理对象
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中找不到 就去三级缓存中找
if (singletonObject == null && allowEarlyReference) {
//这里取得三级缓存中对应的lambda表达式的值--得到原始对象(发生循环依赖但未aop)或者是代理对象(发生循环依赖和aop--提前aop)
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//执行上一步获取的lambda表达式(getEarlyBeanReference方法)
//--有aop,就提前执行AOP--得到一个代理对象
//-- 无aop,就得到一个原始对象
singletonObject = singletonFactory.getObject();// 提前曝光 bean 实例(raw bean),用于解决循环依赖
//将通过三级缓存得到的结果 放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//移除三级缓存中对应的内容
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
三级缓存为什么会移除掉?
在三级缓存中找 找到了就会执行AOp 产出代理对象 然后将代理对象放入到二级缓存。三级缓存一定会能到的对象 但不一定 会执行 aop 二级缓存找不到 才会触发aop(通过lambda表达式,执行函数式接口,执行aop) 产生代理对象放入二级缓存,放入之后需要移除掉对应的三级缓存(保证只执行一次aop)如果三级缓存中对象不需要执行aop操作 ,那么产生的对象仍然要放入二级缓存 ,这是放入的对象是原始对象
为什么单例池:concurentHashmap是,二级缓存是hashmap,三级缓存是hashmap?
三级缓存的AOP过程需要加锁以保证操作的原子性
因为三级缓存的函数接口 内部已经加了锁,保证了操作的原子性 所以没必要使用concurenthashmap
问题:源码中加synchronized锁的意义?
背景:
二级缓存中的aService对象是三级缓存中的lambda表达式生成出来的,
他们是成对的,二级缓存中存在代理对象,则三级缓存中不应该存在lambda表达式;
或者说,三级缓存中存在lambda表达式,则二级缓存中不应当有该代理对象
解答:
- 3级缓存中的 value是一个lambda表达式,一执行就是进行AOP,得到代理对象,所以lambda表达式应当只执行一次,且执行完毕后从3级缓存中进行移除,以防止其他的代码又拿出来执行了
- 在第2、第3级缓存只能有一个地方存在操作对象,要么是lambda表达式(三级缓存),要么是lambda执行后的代理对象(二级缓存)。这是原子性的,为了对高并发情况进行控制,加锁进行同步。
- 1级缓存定义为 concurrentHashMap。 2级、3级缓存定义为简单的HashMap,是因为 2、3级缓存是成对出现的,哪怕是定义成concurrentHashMap,也要加锁保持两个Map的操作的原子性
创建Bean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//得到原始对象 -- 属性未赋值
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//如果当前创建的是单例bean,并且允许着环依赖,并且还在创建过程中,那么则提早暴露--一般均为true
//创建就暴露--一般单例都会暴露出去--都会存入三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//针对发生了循环依赖的情况
//lambda执行的结果存入三级缓存中
//getEarlyBeanReference--wrapIfNecessary方法--判断对象创建过程中是否存在AOP
//--需要,就提前aop,存入代理对象,不需要就存入原始对象
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//暴露原始对象
Object exposedObject = bean;
try {
//属性填充@Autowired --B对象填充原始对象
populateBean(beanName, mbd, instanceWrapper);
//正常情况下进行AOP的地方--postProcessAfterInitialization方法
// --判断是否提前进行了AOP(使用Map:earlyProxyReferences记录提前 进行的aop),如果没有提前aop,才会在这里执行aop
//初始化Bean--可能包含AOP--如果需要AOP,则需要使用原始对象(针对非循环依赖的时候)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
····················
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
其中:
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
是将原始对象信息存入三级缓存的操作,存入的是lambda表达式:
getEarlyBeanReference(beanName, mbd, bean)执行的结果,getEarlyBeanReference会对是否需要提前AOP进行判断,如果需要进行AOP,则生成代理对象放入二级缓存。
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);
}
}
}
其中:
exposedObject = initializeBean(beanName, exposedObject, mbd);
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//对类中某些特殊方法的调用,比如 @PostConstruct,Aware接口
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//InitializingBean接口,afterPropertiesSet,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()) {
//AOP入口
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
整个流程:
1、A doCreateBean()初始化,由于还未创建,从一级缓存查不到,此时只是一个半成品(提前暴露的对象),放入三级缓存singletonFactories;
2、A发现自己需要B对象,但是三级缓存中未发现B,创建B的原始对象,将带有B对象信息(beanName,bd,原始对象)的Lambda表达式放入singletonFactories;
3、B发现自己需要A对象,从一级缓存singletonObjects没找到,并知道了A对象正在创建,就确认发生了循环依赖,这时候再去二级缓存earlySingletonObjects中寻找A对象,没找到就继续在三级缓存singletonFactories中寻找A对象(一定能找到),于是执行三级缓存中的lambda表达式得到一个代理对象或者是原始对象A(A中属性未赋值),将A放入二级缓存earlySingletonObjects,同时从三级缓存删除对应beanName的表达式;
同理向三级缓存加入对象时,也会从二级缓存中将相同BeanName的记录删除掉,所以二级缓存与三级缓存的之间的来两步操作具有原子性。
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
4、将A注入到对象B中;
5、B完成属性填充,执行初始化方法,将自己放入第一级缓存中(此时B是一个完整的对象);
6、A得到对象B,将B注入到A中;
7、A完成属性填充,初始化,并放入到一级缓存中
注意:在对象创建开始的时候,会对对象创建状态利用Set:
singletonsCurrentlyInCreation进行记录:是否是正在创建,可用于判断是否发生了循环依赖。
@Lazy注解的作用: