26.AOP的第三个时机之循环依赖过程中


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的功能。我们用这个功能执行一下就知道了

allowRawInjectionDespiteWrappinghasDependentBean(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! ```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值