highlight: arduino-light
AOP肯定是跟bean的实例化息息相关的,注意,我说的是实例化,而不是生命周期。也就是说,我们AOP肯定是在bean实例化好了后再进行动态代理,想想JDK的动态代理,是需要一个实例化的被代理对象的。
如果你的类被别的类依赖了,那么在依赖获取的过程中进行AOP动态代理。
循环依赖示例代码
先定义2个接口
```java package circle;
public interface LogService {
void log();
} ```
```java package circle;
public interface PrintService {
void print();
} ```
再定义1个切面
```java 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个类。
```java 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"); } } ```
```java 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"); } } ```
测试类
```java 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();
} } ```
循环依赖的过程回顾
```md 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
对照上面的循环依赖过程,稍微走读一下代码。
```java 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);方法中有如下代码:
java 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方法如下
java @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即解决装配。
java 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
```java 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。
java @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
参数allowEarlyReference=true
java @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方法。
java //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
java @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
如下
java 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方法中还会执行代理的逻辑么?如果不会,那么是怎么做到的?
java @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对象已经被代理过,不需要再代理了。
接着往下看
java 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对象是否指向同一个引用
java if (exposedObject == bean) { exposedObject = earlySingletonReference; }
如果是的话,那么执行exposedObject = earlySingletonReference;
为什么这么做?
先看下3个对象分别代表的是什么?
```md
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分支呗
java 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可以执行以下代码。
java !removeSingletonIfCreatedForTypeCheckOnly(getDependentBeans("a")[0])
上面的代码逻辑整理一下就是:如果a对象的bean和exposedObject不相同,那么遍历所有依赖a对象的bean的名称。 判断bean是否被创建,如果已经被创建,那就抛出异常。
为什么呢?
因为所有依赖A的实例,并且已经创建对象的bean依赖的是A的早期引用对象即代理对象earlySingletonReference。
但是要返回的对象也就是要放进去一级缓存的对象是exposedObject。
现在是单例模式,所有要依赖于A的bean和一级缓存里的A的bean应当是一个。
所以如果出现了exposedObject和bean不一样的情况,spring最后抛出了异常:
```java "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从二级缓存移除加入一级缓存。
java 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); } }
以一个问题结束吧
```md
为什么需要二级缓存?为什么需要bean的半成品需要提前暴露一个工厂?
AOP就是一个原因吧!现在有一个实例A,实例B要依赖A,但是A需要被代理,也就是说,A被代理后才能注入给B,那B现在就要注入A,总不能等整个容器所有bean都实例化好后再来注入吧,讲道理也不是不可能,只是spring觉着太麻烦没那个必要,干脆,在注入的时候就直接AOP! ```