AOP肯定是跟bean的实例化息息相关的,注意,我说的是实例化,而不是生命周期。也就是说,我们AOP肯定是在bean实例化好了后再进行动态代理,想想JDK的动态代理,是需要一个实例化的被代理对象的。
如果你的类被别的类依赖了,那么在依赖获取的过程中进行AOP动态代理。
循环依赖示例代码
先定义2个接口
package circle;
public interface LogService {
void log();
}
package circle;
public interface PrintService {
void print();
}
再定义1个切面
package circle;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class Aop implements PriorityOrdered {
//指定切入点表达式,拦截那些方法,即为那些类生成代理对象
//@Pointcut("execution(* com.aop.UserDao.save(..))") ..代表所有参数
//@Pointcut("execution(* com.aop.UserDao.*())") 指定所有的方法
//@Pointcut("execution(* com.aop.UserDao.save())") 指定save方法
@Pointcut("execution(* circle.*.*(..))")
public void pointCut(){
}
@Before("pointCut()")
public void Before(){
System.out.println("Before");
}
@After("pointCut()")
public void After(){
System.out.println("After");
}
@AfterThrowing("pointCut()")
public void AfterThrowing(){
System.out.println("AfterThrowing");
}
@AfterReturning("pointCut()")
public void AfterReturning(){
System.out.println("AfterReturning");
}
@Around("pointCut()")
public void Around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Around Before");
joinPoint.proceed();
System.out.println("Around After");
}
@Override
public int getOrder() {
return 1;
}
}
定义接口的实现类A和B,也是循环依赖的2个类。
package circle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("a")
public class A implements LogService {
@Autowired
private PrintService b;
@Override
public void log() {
System.out.println(b);
System.out.println("log");
}
}
package circle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component("b")
public class B implements PrintService{
@Autowired
private LogService a;
@Override
public void print() {
System.out.println(a);
System.out.println("print");
}
}
测试类
package circle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestCircleCondition {
public static void main(String[] args) {
/**
* 创建一个BeanDefinition读取器 根据注解读取
* 创建一个BeanDefinition扫描器 能够扫描一个类或者包 转换成bd
**/
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
//注册配置类
context.register(BeanConfig.class);
context.refresh();
LogService a = context.getBean("a", LogService.class);
a.log();
PrintService b = context.getBean("b", PrintService.class);
b.print();
}
}
循环依赖的过程回顾
A、B 类 setter 循环依赖的创建过程
1.getSingleton("a", true) 获取a,会从一级缓存中找a(一级缓存该bean为空且当前 bean 正在创建才能去2级缓存拿),然后直接返回空,此时 3 个级别的缓存中都没有 a
2.调用getSingleton(String, ObjectFactory),ObjectFactory是调用createBean方法
sharedInstance = getSingleton(beanName,
() -> {
return createBean(beanName, mbd, args);
});
3.将a添加到正在创建的集合singletonsCurrentlyInCreation中
4.调用 ObjectFactory.getObject()即createBean方法
5.进入doCreateBean方法,推断构造方法、反射调用构造方法实例化bean,这个时候a对象是早期的a,属于半成品。
6.判断需要提前暴露 加入三级缓存放入的是SingletonFactory,SingletonFactory有半成品的引用:
addSingletonFactory(beanName,
() -> getEarlyBeanReference(beanName, mbd, bean));
7.调用 populateBean方法,为a做属性填充操作,注入依赖的对象,发现 setB 需要注入b
8.调用getSingleton(String, ObjectFactory),ObjectFactory是调用createBean方法
sharedInstance = getSingleton(beanName,
() -> {
return createBean(beanName, mbd, args);
});
9.将b添加到正在创建的集合singletonsCurrentlyInCreation中
10.调用 ObjectFactory.getObject()即createBean方法
11.进入doCreateBean方法,反射调用构造方法实例化b,这个时候b对象是早期的b,属于半成品
12.判断需要提前暴露 加入三级缓存:addSingletonFactory(beanName,
() -> getEarlyBeanReference(beanName, mbd, bean));
13.调用populateBean方法,为b做属性填充操作,注入依赖的对象,发现 setA 需要注入a
14.调用 getSingleton("a", true) 获取a,会从3级缓存中找a。
一级缓存该bean为空且当前 bean 正在创建才能去2级缓存拿,2级缓存是空。
2级缓存是空并且允许循环依赖才能从3级缓存拿。
从3级缓存中获取调用ObjectFactory
然后调用ObjectFactory#getObject获取bean。
即调用getEarlyBeanReference方法获取a。
在获取a的时候会提前获取a的代理对象
在获取a的时候会提前获取a的代理对象
在获取a的时候会提前获取a的代理对象
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
//1.不是合成的
//2.存在InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp
= (SmartInstantiationAwareBeanPostProcessor) bp;
//AbstractAutoProxyCreator.getEarlyBeanReference
exposedObject
= ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
此时 a 会从第 3 级缓存中被移到第 2 级缓存,然后将其返回给 b 使用,此时 a 是个半成品(属性还未填充完毕)3级缓存是个工厂,工厂创建对象完毕就没用了,所以需要从三级缓存移除,加入二级缓存
15.b 通过 setA 将 14 中获取的 a 注入到 b 中,b填充属性完毕 然后调用
b= initializeBean("b", b, mbd)
initializeBean方法流程如下:
1.invokeAwareMethods,设置Spring的上下文组件
2.BeanPostProcessor 的 before 方法
3.invokeInitMethods
4.BeanPostProcessor 的 after 方法
16.调用Object earlySingletonReference = getSingleton(beanName, false);
即getSingleton("b", false)获取b,注意这个时候第二个参数是false,这个参数为 false 的时候,只会从前 2 级缓存中尝试获取b,此时1级缓存 2级缓存都没有,只有3级缓存有1个工厂对象,所以获取的是空。
注意:如果不是空会判断initializeBean("b", b, mbd)返回的对象和getSingleton("b", false)获取的对象是不是1个对象。因为对b进行处理完毕,可能对b进行改变,有可能导致b和原始的b不是同一个对象了。
所以需要判断提前暴露的b和原始的b是不是一个对象。
虽然b没有做判断但是a在二级缓存是存在的。所以a做了这个判断判断。
这里最后的返回的是 initializeBean("b", b, mbd)方法返回的对象
此时b创建完毕 最后b会从第2 3级缓存中被移除,然后被丢到1级缓存
注意b没有进入二级缓存
注意b没有进入二级缓存
注意b没有进入二级缓存
17.b 返回给 a,然后 b 被通过 A 类中的 setB 注入给 a
18.a 的 populateBean 执行完毕,即:完成属性填充,到此时 a 已经注入到 b 中了
19.调用a= initializeBean("a", a, mbd)对 a 进行处理,这个内部可能对 a 进行改变,有可能导致 a 和原始的 a 不是同一个对象了
1.invokeAwareMethods,设置Spring的上下文组件
2.BeanPostProcessor 的 before 方法
3.invokeInitMethods
4.BeanPostProcessor 的 after 方法
20.调用getSingleton("a", false)获取 a,注意这个时候第二个参数是 false,这个参数为 false 的时候,只会从前 2 级缓存中尝试获取 a,而 a 在步骤 11 中已经被丢到了第 2 级缓存中,所以此时这个可以获取到 a,这个 a 已经被注入给 b 了。
因为对a进行处理完毕,可能对a进行改变,有可能导致a和原始的a不是同一个对象了。所以需要判断提前暴露的a和原始的a是不是一个对象。
所以这里最后的返回的是 initializeBean("a", a, mbd) 的对象
此时a创建完毕 最后a会从第2 3级缓存中被移除,然后被丢到1级缓存
21.此时判断注入给 b 的 a 和通过initializeBean方法产生的 a 是否是同一个 a,不是同一个,则弹出异常
22.此时a创建完毕 最后b会从第2 3级缓存中被移除,然后被丢到1级缓存
循环依赖过程中的AOP
对照上面的循环依赖过程,稍微走读一下代码。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
/***
* 创建bean实例 仅仅是创建bean实例
* 1.判断是否存在Supplier和Factory-Method如果有那么就使用并创建实例
* 否则就选择使用构造函数进行构造
* 2.计算构造函数至少有几个参数 选择构造函数
* 3.选择构造函数的参数 下标&通用
* 4.计算构造函数的参数权重
* instanceWrapper实现了 ConfigurablePropertyAccessor
* 是一个包装类 该类的属性可以编辑
* instanceWrapper有一个属性WrappedInstance 里面放的就是我们构造的实例
*/
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
//允许 post-processors 修改 beanDefinition
//这里都已经构造完了实例 在修改beanDefinition 有什么意义呢?
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//调用 MergedBeanDefinitionPostProcessor
//查找出满足条件的属性、方法, 将他们封装起来, 以便后面在填充属性的时候可以直接使用
//https://juejin.cn/post/6844904167945797640
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 comresolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
/***
* 是否需要提前暴露
* 判断条件:
* 1.是单例
* 2.允许循环依赖
* 3.bean正在被创建
*/
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");
}
/***
* singletonObjects 一级缓存池
* earlySingletonObjects 二级缓存池
* singletonFactories 三级缓存池
* 将ObjectFactory<?> singletonFactory 加入三级缓存 singletonFactories
*/
//getEarlyBeanReference放入了提前实例化但是未初始化的对象
//getEarlyBeanReference中获取了所有的SmartInstantiationAwareBeanPostProcessor并调用
//SmartInstantiationAwareBeanPostProcessor中getEarlyBeanReference是一个默认方法
//默认返回的是传入的bean
addSingletonFactory( beanName,() -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
//这个bean已经放入了 getEarlyBeanReference(beanName, mbd, bean)
Object exposedObject = bean;
try {
/***
* 1.属性填充
* 2.处理属性依赖
* 传入的是 BeanWrapper
*/
populateBean(beanName, mbd, instanceWrapper);
/***
* 初始化bean
* 如果bean实现了以下接口
* BeanNameAware, BeanFactoryAware, ApplicationContextAware
* 则调用对应接口的方法
* 注意最后bean的代理对象就是在这里被创建的
*/
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);
}
}
/***
* 是否需要提前暴露 earlySingletonExposure = true
* 判断条件:
* 1.是单例
* 2.允许循环依赖
* 3.bean正在被创建
*/
if (earlySingletonExposure) {
// A 和 B 循环依赖
// 对于A来说
// 如果没有循环依赖不会从三级缓存获取 这里直接返回空
// 如果没有循环依赖 返回空 因为allowEarlyReference是false 所以不会不到三级缓存拿
// 如果有循环依赖 在B填充属性A对象时 会在填充属性的方法中调用 getSingleton(beanName, true);
// 因为allowEarlyReference是true 所以会到三级缓存拿 并放入二级缓存
// 然后在这里获取的就是二级缓存中的对象
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
//判断代理的对象和提前暴露的对象是不是还是一个 注意使用的是 ==
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
//如果不是一个判断是否有依赖该bean的对象
}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
//如果有抛出异常
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
在创建A的实例的时候调用了doCreateBean方法。
1.createBeanInstance(beanName, mbd, args);创建了A的实例
2.addSingletonFactory( beanName,() -> getEarlyBeanReference(beanName, mbd, bean));将A的实例放了三级缓存,其中bean就是A的实例
3.populateBean(beanName, mbd, instanceWrapper);为A的实例填充属性,instanceWrapper是A的实例的包装对象。
4.在populateBean(beanName, mbd, instanceWrapper);方法中有如下代码:
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
遍历InstantiationAwareBeanPostProcessor,其中有1个AutowiredAnnotationBeanPostProcessor。
它的postProcessProperties方法如下
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
/***
metadata = {InjectionMetadata@2239}
targetClass = {Class@1785} "class circle.A"
injectedElements = {ArrayList@2272} size = 1
0 ="AutowiredFieldElement for private circle.PrintService circle.A.b"
number = {Field@2262}private circle.PrintService circle.A.b
checkedElements = {LinkedHashSet@2268} size = 1
0 ="AutowiredFieldElement for private circle.PrintService circle.A.b"
number = {Field@2262}private circle.PrintService circle.A.b
***/
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
可以看到A实例需要自动装配的字段是b,此时会遍历所有的element依次resolve即解决装配。
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
Collection<InjectedElement> checkedElements = this.checkedElements;
Collection<InjectedElement> elementsToIterate =
(checkedElements != null ? checkedElements : this.injectedElements);
if (!elementsToIterate.isEmpty()) {
for (InjectedElement element : elementsToIterate) {
if (logger.isTraceEnabled()) {
logger.trace("Processing injected element of bean '" + beanName + "': " + element);
}
element.inject(target, beanName, pvs);
}
}
}
element.inject(target, beanName, pvs);最后会调用DependencyDescriptor#resolveCandidate
public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
throws BeansException {
return beanFactory.getBean(beanName);
}
此时beanFactory.getBean(beanName);触发B的实例化和初始化
在创建B的实例的时候调用了doCreateBean方法。
1.createBeanInstance(beanName, mbd, args);创建了B的实例
2.addSingletonFactory( beanName,() -> getEarlyBeanReference(beanName, mbd, bean));将B的实例放了三级缓存,其中bean就是B的实例
3.populateBean(beanName, mbd, instanceWrapper);为B的实例填充属性,instanceWrapper是B的实例的包装对象。
然后开始B实例需要自动装配的字段是b,此时会遍历所有的element依次resolve即解决装配。
最后在DependencyDescriptor#resolveCandidate方法中调用beanFactory.getBean(beanName);寻找A。
这里的参数name是a。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
参数allowEarlyReference=true
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
/**
* 这个singletonObjects就是微观层面的IOC容器,循环创建刚开始时,IOC确实是空的。
* 但是我前面一开始的getBean()方法是存在递归调用现象的直接举2个例子:
* 第一:假如现在在实例化A,结果有发现需要给A注入B,
* 那Spring是不是得获得B,怎么获得呢? 递归使用getBean(BName)完成,
* 第二个例子: A被添加上了@Lazy注解,是懒加载的,但是终究有一个会通过getBean(AName)获取A,
* 这是发现A是实例化需要B,B肯定已经实例化完事了,同样是通过递归getBean(BName)实现注入,
* 在这两个过程中就是getSingleton()保证不会重复创建已经存在的实例
*/
//是否应创建早期引用 allowEarlyReference is true
Object singletonObject = this.singletonObjects.get(beanName);
//一级缓存中该bean为空 且 当前 bean 正在创建才能去2级缓存拿
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//2级缓存中获取
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) {
//3级缓存中获取 获取的是一个ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//调用ObjectFactory的getObject方法获取对象
singletonObject = singletonFactory.getObject();
//放入2级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//从3级缓存移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
先从一级缓存和二级缓存中拿a,没拿到会从三级缓存中拿a。三级缓存是1个ObjectFactory。
调用ObjectFactory的getObject方法获取对象a。
ObjectFactory的getObject方法对应的是getEarlyBeanReference方法。
//bean就是被我们刚刚创建的实例
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
//AbstractAutoProxyCreator.getEarlyBeanReference
SmartInstantiationAwareBeanPostProcessor ibp
= (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
调用AnnotationAwareAspectJAutoProxyCreator#getEarlyBeanReference
最后调用的是AbstractAutoProxyCreator#getEarlyBeanReference
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
//创建代理的开始
return wrapIfNecessary(bean, beanName, cacheKey);
}
最后wrapIfNecessary(bean, beanName, cacheKey);返回了1个exposedObject,就是a的代理对象。
ok,b初始化生命周期执行完毕,又回到了a的初始化生命周期。
a对象对应的BeanWrapper如下
instanceWrapper = {BeanWrapperImpl@1864} "org.springframework.beans.BeanWrapperImpl:
wrapping object [circle.A@6f204a1a]"
可以看到a的实例是circle.A@6f204a1a
接着执行exposedObject = initializeBean(beanName, exposedObject, mbd);
initializeBean方法中的AbstractAutoProxyCreator#postProcessAfterInitialization不就是我们上一篇文章讲的第二个aop的时机么?那么在initializeBean方法中还会执行代理的逻辑么?如果不会,那么是怎么做到的?
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
this.earlyProxyReferences中的对象只有1个,就是circle.A@6f204a1a
那么this.earlyProxyReferences.remove(cacheKey)返回了true,说明早期代理引用中的代理对象和当前对象是1个,那也就说明a对象已经被代理过,不需要再代理了。
接着往下看
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<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException();
}
}
}
}
首先从二级缓存拿出来了我们的代理对象引用earlySingletonReference即circle.A@6f204a1a
接着有个判断,判断代理后的a对象和a对象是否指向同一个引用
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
如果是的话,那么执行exposedObject = earlySingletonReference;为什么这么做?
先看下3个对象分别代表的是什么?
bean即a对象是spring通过反射创建的对象。
exposedObject即a对象的暴露对象,是a对象经过了下面2个方法以后的对象。
`populateBean(beanName, mbd, instanceWrapper);`
`exposedObject = initializeBean(beanName, exposedObject, mbd);`
earlySingletonReference是a对象的代理对象,earlySingletonReference持有a对象的引用A@1869。
earlySingletonReference = {$Proxy22@2467} "circle.A@6f204a1a"
h = {JdkDynamicAopProxy@2598}
advised = {ProxyFactory@2627}
targetSource = {SingletonTargetSource@2631}
target = {A@1869}
那也就是说如果bean对象和经过populateBean方法以及initializeBean方法以后的exposedObject是1个对象。
还会有不一样的情况吗?当然有,如果你的后置处理器改变了引用呢?比如我在我的后置处理器重新创建1个A对象。
那么会怎么样呢?进入else if分支呗
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException();
}
}
还好idea自带evaluate expression的功能。我们用这个功能执行一下就知道了
allowRawInjectionDespiteWrapping 和 hasDependentBean(beanName)都为true
getDependentBeans(beanName);返回1个String数组,里面是所有依赖a对象的bean的名称即b。
接下来遍历所有依赖a对象的bean,判断是否已经被创建,如果已经被创建返回的是false。
protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
removeSingleton(beanName);
return true;
}
else {
return false;
}
}
因为b已经被创建了。所以返回false。
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean))返回的是true。
使用idea可以执行以下代码。
!removeSingletonIfCreatedForTypeCheckOnly(getDependentBeans("a")[0])
上面的代码逻辑整理一下就是:如果a对象的bean和exposedObject不相同,那么遍历所有依赖a对象的bean的名称。 判断bean是否被创建,如果已经被创建,那就抛出异常。
为什么呢?
因为所有依赖A的实例,并且已经创建对象的bean依赖的是A的早期引用对象即代理对象earlySingletonReference。
但是要返回的对象也就是要放进去一级缓存的对象是exposedObject。
现在是单例模式,所有要依赖于A的bean和一级缓存里的A的bean应当是一个。
所以如果出现了exposedObject和bean不一样的情况,spring最后抛出了异常:
"Bean with name a has been injected into other beans [b] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."
翻译
作为循环引用的一部分,名为a的Bean在其原始版本中被注入到其他Bean中,但最终被封装。这意味着其它bean使用的不是a的最终版本。这通常是过度渴望类型匹配的结果,例如,考虑在关闭“allowEagleInit”标志的情况下使用“getBeanNameForType”。
最后如果exposedObject == bean 那么 exposedObject = earlySingletonReference;
exposedObject = earlySingletonReference;相当于bean= earlySingletonReference;
此时3者指向的都是同一个对象即代理对象。AbstractAutowireCapableBeanFactory#doCreateBean返回了exposedObject即earlySingletonReference。
最后通过DefaultSingletonBeanRegistry#addSingleton将a从二级缓存移除加入一级缓存。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
以一个问题结束吧
为什么需要二级缓存?为什么需要bean的半成品需要提前暴露一个工厂?
AOP就是一个原因吧!现在有一个实例A,实例B要依赖A,但是A需要被代理,也就是说,A被代理后才能注入给B,那B现在就要注入A,总不能等整个容器所有bean都实例化好后再来注入吧,讲道理也不是不可能,只是spring觉着太麻烦没那个必要,干脆,在注入的时候就直接AOP!