mini-Spring 高级设计篇:Step 16:通过三级缓存解决循环依赖

问题:

在 Spring 框架中,循环依赖指多个 Bean 之间形成依赖闭环的现象,主要分为三种类型:

  • 自身依赖于自身、
  • 互相循环依赖、
  • 多组循环依赖。

按照现在的程序,一旦出现循环依赖,就会进入递归循环创建对象的无底洞,从而爆栈。

解决思路:

Spring通过三级缓存机制解决此问题,该机制允许多阶段管理Bean实例,支持早期暴露半成品对象以打破循环,同时兼容AOP代理等扩展功能。

Spring使用三级缓存管理Bean的不同创建阶段:

  • 一级缓存(singletonObjects):存储完全初始化的Bean实例(属性填充和初始化方法执行完毕)。
  • 二级缓存(earlySingletonObjects):存储早期暴露的半成品Bean实例(实例化但属性未填充)。
  • 三级缓存(singletonFactories):存储ObjectFactory,用于创建早期Bean引用,支持AOP代理生成。

目前实际只完成了一级缓存。
而二级缓存可以简单解决循环依赖问题,但是二级缓存无法解决 AOP 场景中代理对象与原始对象引用不一致的问题,因此需要三级缓存。

三级缓存的优势:

  • 支持AOP:三级缓存允许在早期暴露时生成代理对象,而非直接存储实例。
  • 分离成品和半成品对象,避免污染一级缓存。

解决循环依赖的机制

核心类:

  • DefaultSingletonBeanRegistry:管理三级缓存,提供getSingleton、addSingletonFactory等方法。
  • AbstractAutowireCapableBeanFactory:处理Bean创建,包括早期暴露和属性填充。

解决步骤:

  1. 实例化Bean:创建Bean实例后,如果是单例且允许循环依赖,添加ObjectFactory到三级缓存(addSingletonFactory),用于生成早期引用。
  2. 获取依赖:在属性填充时,通过getSingleton方法按序查询:
    • 先查一级缓存。
    • 若无,查二级缓存。
    • 若无,查三级缓存:执行ObjectFactory.getObject()生成早期实例(若需AOP,则生成代理),移入二级缓存。
  3. 处理循环:如果存在循环,依赖方可从二级或三级缓存获取早期实例,打破递归。
  4. 完成初始化:属性填充和初始化方法执行后,将实例移入一级缓存(addSingleton),移除二级和三级缓存条目。

对于AOP:getEarlyBeanReference方法在三级缓存中处理代理创建,确保代理对象在循环中被一致引用。

举例说明,引出问题:

背景: A,B循环依赖,且A被代理。

开始get A:A在实例化后,紧接着就提前暴露三级缓存(仅单例),这里只是保存该bean的创建方法,还没有执行。然后进入注入,创建B, B在属性注入式就拿到了A的第三级缓存,并执行A工厂的getObject拿到了A(的代理对象),存入第二级缓存(见getSingleton方法),走完B的创建过程,回到了A的属性注入过程,走完B的创建过程

此处就有几个问题\值得关注的点:⭐⭐⭐⭐⭐(原教材没讲或者直接忽略了)

  1. “B在属性注入式就拿到了A的第三级缓存,并执行A工厂的getObject拿到了A(的代理对象),存入第二级缓存” 在这一步得到了A的代理对象,但是这个代理对象的属性还没有填充。
  2. 属性未填充并不影响 AOP 增强?。
    • AOP 增强是基于方法拦截实现的,与目标对象的属性状态无关
  3. B的流程结束后执行的是原始A的逻辑(包括属性填充),但最后管理、返回的应该是A的代理对象:
    • 代理对象始终持有目标对象的引用:所以原始对象填充属性了也会反映到代理对象
    • initializeBean的最后阶段,Spring 会用二级缓存中的A的代理对象 P 替换原始对象 A。(同时也避免了二次代理)
  4. 就像上面说的,原始对象A在注入B时就产生了代理,后面不会再次代理,是有两个机制共同保证的:
    • 1.上文中的“initializeBean的最后阶段会用二级缓存中的A的代理对象 P 替换原始对象 A”
    • 2.自动代理创建器(DefaultAdvisorAutoProxyCreator)的earlyProxyReferences记录了哪些 Bean 已经被生成过代理,避免二次代理。

以上问题的代码实现见下。我会在注释里再次讨论。

具体实现:

0.工程结构:

small-spring-step-16
└── src
    ├── main
    │   └── java
    │       └── cn.bugstack.springframework
    │           ├── aop
    │           │   ├── aspectj
    │           │   │   └── AspectJExpressionPointcut.java
    │           │   │   └── AspectJExpressionPointcutAdvisor.java
    │           │   ├── framework 
    │           │   │   ├── adapter
    │           │   │   │   └── MethodBeforeAdviceInterceptor.java
    │           │   │   ├── autoproxy
    │           │   │   │   └── MethodBeforeAdviceInterceptor.java
    │           │   │   ├── AopProxy.java
    │           │   │   ├── Cglib2AopProxy.java
    │           │   │   ├── JdkDynamicAopProxy.java
    │           │   │   ├── ProxyFactory.java
    │           │   │   └── ReflectiveMethodInvocation.java
    │           │   ├── AdvisedSupport.java
    │           │   ├── Advisor.java
    │           │   ├── BeforeAdvice.java
    │           │   ├── ClassFilter.java
    │           │   ├── MethodBeforeAdvice.java
    │           │   ├── MethodMatcher.java
    │           │   ├── Pointcut.java
    │           │   ├── PointcutAdvisor.java
    │           │   └── TargetSource.java
    │           ├── beans
    │           │   ├── factory  
    │           │   │   ├── annotation
    │           │   │   │   ├── Autowired.java
    │           │   │   │   ├── AutowiredAnnotationBeanPostProcessor.java
    │           │   │   │   ├── Qualifier.java
    │           │   │   │   └── Value.java
    │           │   │   ├── config
    │           │   │   │   ├── AutowireCapableBeanFactory.java
    │           │   │   │   ├── BeanDefinition.java
    │           │   │   │   ├── BeanFactoryPostProcessor.java
    │           │   │   │   ├── BeanPostProcessor.java
    │           │   │   │   ├── BeanReference.java
    │           │   │   │   ├── ConfigurableBeanFactory.java
    │           │   │   │   ├── InstantiationAwareBeanPostProcessor.java
    │           │   │   │   └── SingletonBeanRegistry.java
    │           │   │   ├── support
    │           │   │   │   ├── AbstractAutowireCapableBeanFactory.java
    │           │   │   │   ├── AbstractBeanDefinitionReader.java
    │           │   │   │   ├── AbstractBeanFactory.java
    │           │   │   │   ├── BeanDefinitionReader.java
    │           │   │   │   ├── BeanDefinitionRegistry.java
    │           │   │   │   ├── CglibSubclassingInstantiationStrategy.java
    │           │   │   │   ├── DefaultListableBeanFactory.java
    │           │   │   │   ├── DefaultSingletonBeanRegistry.java
    │           │   │   │   ├── DisposableBeanAdapter.java
    │           │   │   │   ├── FactoryBeanRegistrySupport.java
    │           │   │   │   ├── InstantiationStrategy.java
    │           │   │   │   └── SimpleInstantiationStrategy.java  
    │           │   │   ├── support
    │           │   │   │   └── XmlBeanDefinitionReader.java
    │           │   │   ├── Aware.java
    │           │   │   ├── BeanClassLoaderAware.java
    │           │   │   ├── BeanFactory.java
    │           │   │   ├── BeanFactoryAware.java
    │           │   │   ├── BeanNameAware.java
    │           │   │   ├── ConfigurableListableBeanFactory.java
    │           │   │   ├── DisposableBean.java
    │           │   │   ├── FactoryBean.java
    │           │   │   ├── HierarchicalBeanFactory.java
    │           │   │   ├── InitializingBean.java
    │           │   │   ├── ListableBeanFactory.java
    │           │   │   ├── ObjectFactory.java
    │           │   │   └── PropertyPlaceholderConfigurer.java
    │           │   ├── BeansException.java
    │           │   ├── PropertyValue.java
    │           │   └── PropertyValues.java 
    │           ├── context
    │           │   ├── annotation
    │           │   │   ├── ClassPathBeanDefinitionScanner.java 
    │           │   │   ├── ClassPathScanningCandidateComponentProvider.java 
    │           │   │   └── Scope.java 
    │           │   ├── event
    │           │   │   ├── AbstractApplicationEventMulticaster.java 
    │           │   │   ├── ApplicationContextEvent.java 
    │           │   │   ├── ApplicationEventMulticaster.java 
    │           │   │   ├── ContextClosedEvent.java 
    │           │   │   ├── ContextRefreshedEvent.java 
    │           │   │   └── SimpleApplicationEventMulticaster.java 
    │           │   ├── support
    │           │   │   ├── AbstractApplicationContext.java 
    │           │   │   ├── AbstractRefreshableApplicationContext.java 
    │           │   │   ├── AbstractXmlApplicationContext.java 
    │           │   │   ├── ApplicationContextAwareProcessor.java 
    │           │   │   └── ClassPathXmlApplicationContext.java 
    │           │   ├── ApplicationContext.java 
    │           │   ├── ApplicationContextAware.java 
    │           │   ├── ApplicationEvent.java 
    │           │   ├── ApplicationEventPublisher.java 
    │           │   ├── ApplicationListener.java 
    │           │   └── ConfigurableApplicationContext.java
    │           ├── core.io
    │           │   ├── ClassPathResource.java 
    │           │   ├── DefaultResourceLoader.java 
    │           │   ├── FileSystemResource.java 
    │           │   ├── Resource.java 
    │           │   ├── ResourceLoader.java
    │           │   └── UrlResource.java
    │           ├── stereotype
    │           │   └── Component.java
    │           └── utils
    │               ├── ClassUtils.java
    │               └── StringValueResolver.java
    └── test
        └── java
            └── cn.bugstack.springframework.test
                ├── bean
                │   ├── Husband.java
                │   ├── HusbandMother.java
                │   ├── IMother.java
                │   ├── SpouseAdvice.java  
                │   └── Wife.java
                ├── ApiTest.java
                └── CircleTest.java  

1.定义ObjectFactory接口:

/**
 * 对象工厂接口,用于返回指定类型的对象实例。
 * - 可能返回共享的单例对象,也可能返回新的独立对象,取决于具体实现。
 * - 在 Spring 三级缓存中,常用于提前暴露 Bean 的引用,以解决循环依赖问题。
 */
public interface ObjectFactory<T> {

    /**
     * 获取对象实例
     *
     * @return 返回指定类型的对象
     * @throws BeansException 获取过程中可能抛出的异常
     */
    T getObject() throws BeansException;

}

2. 设置三级缓存

DefaultSingletonBeanRegistry

public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
    // 一级缓存,普通对象
    private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();

    // 二级缓存,提前暴漏对象,没有完全实例化的对象
    protected final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>();

    // 三级缓存,存放代理对象
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>();

    //注册了销毁回调的 Bean 对象的容器
    private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();


    /** 缓存中用于表示 null 值的特殊标记对象,避免存储 null 导致异常 */
    protected static final Object NULL_OBJECT = new Object();

    /**
     * 销毁所有单例 Bean 对象。
     *
     * 该方法会遍历容器中所有已注册的实现了 DisposableBean 接口的 Bean(存储在 disposableBeans 中),
     * 并按注册顺序的逆序依次调用它们的 destroy() 方法完成销毁。
     *
     * 逆序销毁是为了保证依赖关系正确释放(先销毁依赖者,再销毁被依赖者)。
     *
     * 销毁过程中如果发生异常,会包装成 BeansException 并抛出,确保调用者能感知销毁失败。
     */
    public void destroySingletons() {
        Set<String> keySet = this.disposableBeans.keySet();
        Object[] disposableBeanNames = keySet.toArray();

        //i倒序遍历:逆序销毁时因为被加入容器的顺序就暗含了依赖顺序
        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            Object beanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }
        }
    }


    @Override
    public Object getSingleton(String beanName) {
        // 1. 优先从一级缓存获取(完全初始化的单例对象)
        Object singletonObject = singletonObjects.get(beanName);
        if (null == singletonObject) {
            // 2. 一级缓存没有,则从二级缓存获取(半成品对象/代理对象)
            singletonObject = earlySingletonObjects.get(beanName);
            if (null == singletonObject) {
                // 3. 二级缓存也没有,则从三级缓存获取(ObjectFactory 提前暴露的对象工厂)
                ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 通过工厂创建对象(可能是代理对象)
                    singletonObject = singletonFactory.getObject();
                    // 放入二级缓存,并移除三级缓存
                    earlySingletonObjects.put(beanName, singletonObject);
                    singletonFactories.remove(beanName);
                }
            }
        }
        return singletonObject;
    }

    /**
     * 注册单例对象到一级缓存,同时清理二、三级缓存
     */
    public void registerSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
        earlySingletonObjects.remove(beanName);
        singletonFactories.remove(beanName);
    }

    /**
     * 向三级缓存添加对象工厂,用于提前暴露对象
     */
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory){
        if (!this.singletonObjects.containsKey(beanName)) {
            // 如果一级缓存中没有成品对象
            // 1. 将对象工厂放入三级缓存(用于生成代理或提前引用)
            this.singletonFactories.put(beanName, singletonFactory);
            // 2. 移除二级缓存中的半成品对象(优先保证代理对象生效)
            this.earlySingletonObjects.remove(beanName);
        }

    }

    /**
     * 注册需要销毁的 Bean(容器关闭时调用 destroy)
     */
    public void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }

}

3.提前暴露对象:

核心原则

  • 在实例化 Bean 之后、属性注入前,把 Bean 放入三级缓存。
  • 在注入属性时,如果发现依赖 Bean 正在创建,就先从二级或三级缓存拿,避免无限递归。

3.1首先扩展一下InstantiationAwareBeanPostProcessor:

添加:

/**
     * 在 Bean 对象执行初始化方法之后,执行此方法
     *
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;


    /**
     * 用于提前斯暴露Bean的引用,解决循环依赖问题
     * 属于InstantiationAwareBeanPostProcessor接口的默认方法
     * @param bean 实例化后的Bean对象
     * @param beanName Bean的名称
     * @return 早期暴露的Bean引用(默认返回原始Bean)
     */
    default Object getEarlyBeanReference(Object bean, String beanName) {
        return bean;
    }

3.2 DefaultAdvisorAutoProxyCreator新增earlyProxyReferences及相关机制:

/**
 * 自动代理创建器,自动扫描容器中所有的 AspectJExpressionPointcutAdvisor,
 * 根据切点匹配结果对目标Bean生成代理。
 *
 * 实现了 InstantiationAwareBeanPostProcessor,可以在 Bean 实例化前替换成代理对象。
 */
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {

    private DefaultListableBeanFactory beanFactory;

    // 记录已经生成过早期代理对象的 Bean 名称
    private final Set<Object> earlyProxyReferences =
            Collections.synchronizedSet(new HashSet<>());

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        // 这里强转是为了方便后续调用 getBeansOfType 方法
        this.beanFactory = (DefaultListableBeanFactory) beanFactory;
    }

    /**
     * 在 Bean 实例化之前尝试返回代理对象。
     * @param beanClass 待创建Bean的类
     * @param beanName  Bean名称
     * @return 如果匹配切面返回代理,否则返回 null 继续创建原Bean
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 目前先直接返回null,后期处理循环依赖问题时才需要提前创建代理对象并暴露
        return null;
    }

    /**
     * 判断是否为Spring基础设施类,避免代理这些类。
     */
    private boolean isInfrastructureClass(Class<?> beanClass) {
        return Advice.class.isAssignableFrom(beanClass) ||
                Pointcut.class.isAssignableFrom(beanClass) ||
                Advisor.class.isAssignableFrom(beanClass);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 不做处理,直接返回原始bean
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (!earlyProxyReferences.contains(beanName)) {
            return wrapIfNecessary(bean, beanName);
        }
        // 已经提前代理过,直接返回早期代理对象,避免二次代理
        return bean;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        return pvs;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
        earlyProxyReferences.add(beanName);
        return wrapIfNecessary(bean, beanName);
    }

    private Object wrapIfNecessary(Object bean, String beanName) {
        // 排除Spring自身基础设施类,防止循环代理
        if (isInfrastructureClass(bean.getClass())) {
            return bean; // 不代理,直接返回原对象
        }

        // 获取所有切面通知组合对象
        Collection<AspectJExpressionPointcutAdvisor> advisorCollection =
                beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();

        List<AspectJExpressionPointcutAdvisor> advisors = new ArrayList<>(advisorCollection);


        // 准备代理相关配置
        AdvisedSupport advisedSupport = new AdvisedSupport();
        advisedSupport.setTargetSource(new TargetSource(bean));
        advisedSupport.setProxyTargetClass(bean.getClass().getInterfaces().length == 0);


        // 遍历所有的切面通知器(Advisor)
        for (AspectJExpressionPointcutAdvisor advisor : advisors) {
            // 检查当前通知器的切入点是否匹配目标Bean的类
            // getClassFilter()获取类过滤器,matches()判断目标类是否符合切入点表达式
            if (advisor.getPointcut().getClassFilter().matches(bean.getClass())) {
                // 如果匹配,则将该通知器添加到通知支持类中
                advisedSupport.addAdvisor(advisor); // 存储匹配的通知器
            }
        }

        // 检查是否有匹配的通知器
        if (!advisedSupport.getAdvisors().isEmpty()) {
            // 如果有匹配的通知器,使用代理工厂创建代理对象并返回
            return new ProxyFactory(advisedSupport).getProxy();
        }
        // 如果没有匹配的通知器,直接返回原始Bean对象
        return bean;
    }


}

3.3AbstractAutowireCapableBeanFactory

注意提前暴露机制与initializeBean的改动。

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    //定义了一个创建对象的实例化策略属性类 InstantiationStrategy instantiationStrategy,这里我们选择了 Cglib 的实现类
    private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {

        Object bean = null;

        try {
            // 提前代理,提供一个机会来返回一个自定义的 bean 实例,从而跳过 Spring 默认的 bean 实例化、属性注入等流程。
            bean = resolveBeforeInstantiation(beanName, beanDefinition);
            if (null != bean) {
                return bean;
            }
        } catch (Exception e) {
            throw new BeansException("Failed during resolveBeforeInstantiation for bean: " + beanName, e);
        }

        try {
            // 创建实例
            bean = createBeanInstance(beanDefinition, beanName, args);
        } catch (Exception e) {
            throw new BeansException("Failed to create bean instance for: " + beanName, e);
        }

        // --- 提前暴露三级缓存(仅单例) ---
        //这里只是保存该bean的创建方法,还没有执行
        /**
         * 执行时机:
         * 假设这里A被代理,创建A,暴露了第三级缓存,进入属性注入,创建B,
         * B在属性注入式就拿到了A的第三级缓存,并执行A工厂的getObject拿到了A(的代理对象),存入第二级缓存(见getSingleton方法),走完B的创建过程,
         * 回到了A的属性注入过程,走完B的创建过程
         */
        if (beanDefinition.isSingleton()) {
            Object finalBean = bean;
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, beanDefinition, finalBean));
        }

        // -----------------------------
        // postProcessAfterInstantiation,可能阻止属性注入
        // -----------------------------
        boolean continueWithPropertyPopulation = applyBeanPostProcessorsAfterInstantiation(beanName, bean);
        if (!continueWithPropertyPopulation) {
            return bean; // 不再进行属性填充
        }


        try {
            // 在设置 Bean 属性之前,允许 AutowiredAnnotationBeanPostProcessor 修改属性值(@Autowired、@Value)
            applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Failed to process @Autowired/@Value annotations for bean: " + beanName, e);
        }

        try {
            // 注入属性
            applyPropertyValues(bean, beanName, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Failed to apply property values for bean: " + beanName, e);
        }

        try {
            // 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法
            bean = initializeBean(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Failed to initialize bean: " + beanName, e);
        }


        //注册可销毁的 Bean
        registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);

        // 判断 SCOPE_SINGLETON、SCOPE_PROTOTYPE
        Object exposedObject = bean;
        if (beanDefinition.isSingleton()) {
            // 获取代理对象
            exposedObject = getSingleton(beanName);
            registerSingleton(beanName, exposedObject);
        }
        return exposedObject;
    }

    /**
     * 获取Bean的早期引用,用于处理循环依赖
     * 会遍历所有BeanPostProcessor,执行其getEarlyBeanReference方法
     * @param beanName Bean名称
     * @param beanDefinition Bean的定义信息
     * @param bean 原始Bean实例
     * @return 经过处理后的早期暴露引用(可能被增强,如AOP代理)
     */
    protected Object getEarlyBeanReference(String beanName, BeanDefinition beanDefinition, Object bean) {
        Object exposedObject = bean;
        // 遍历所有Bean后置处理器
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // 只处理InstantiationAwareBeanPostProcessor类型的处理器
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                // 调用处理器的早期引用方法进行处理
                Object current = ((InstantiationAwareBeanPostProcessor) bp)
                        .getEarlyBeanReference(exposedObject, beanName);
                // 如果处理器返回了新的引用,则更新暴露的引用
                if (current != null) {
                    exposedObject = current;
                }
            }
        }
        // 返回最终处理后的早期引用
        return exposedObject;
    }


    /**
     * 初始化 Bean 的过程:
     * 1. 调用实现了 Aware 接口的回调方法,注入相应的容器资源。
     * 2. 执行所有 BeanPostProcessor 的 postProcessBeforeInitialization 方法。
     * 3. 调用 Bean 自定义的初始化方法(如 afterPropertiesSet 或配置的 init-method)。
     * 4. 执行所有 BeanPostProcessor 的 postProcessAfterInitialization 方法。
     */
    private Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {

        // 1. 处理Aware接口回调(注入容器核心资源)
        // 让Bean能够感知到容器相关信息(如Bean名称、BeanFactory等)
        if (bean instanceof Aware) {
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(this);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
            }
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
        }

        // 2. 执行初始化前置处理器(BeanPostProcessor)
        // 例如:@PostConstruct注解标注的方法会在此阶段执行
        Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

        // 3. 执行Bean自身的初始化方法
        try {
            // 调用InitializingBean接口的afterPropertiesSet方法
            // 或自定义的init-method初始化方法
            // 此时Bean的属性已完成填充,可执行初始化逻辑
            invokeInitMethods(beanName, wrappedBean, beanDefinition);
        } catch (Exception e) {
            throw new BeansException("Invocation of init method of bean[" + beanName + "] failed", e);
        }

        // 4. 执行初始化后置处理器
        // 无循环依赖时:AOP代理在此阶段通过wrapIfNecessary创建
        // 有循环依赖时:因advisedBeans缓存直接返回原始对象(早期代理已创建)
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

        // 5. 循环依赖场景:复用早期代理对象(核心逻辑)
        // 从二级缓存获取早期暴露的代理对象(若存在)
        Object earlySingletonReference = getSingleton(beanName);

        if (earlySingletonReference != null) {
            // 若经过后置处理后仍是原始对象,说明需要替换为早期代理
            // 保证最终返回的是代理对象,与循环依赖中已注入的对象一致
            if (wrappedBean == bean) {
                wrappedBean = earlySingletonReference;
            }
        }

        // 最终返回的对象:
        // - 无循环依赖:正常代理对象或原始对象
        // - 有循环依赖:早期创建的代理对象(保证引用一致性)
        return wrappedBean;
    }



    /**
     * 调用 Bean 的初始化方法
     */
    private void invokeInitMethods(String beanName, Object wrappedBean, BeanDefinition beanDefinition) throws Exception {
        // 1. 实现接口 InitializingBean
        if (wrappedBean instanceof InitializingBean) {
            ((InitializingBean) wrappedBean).afterPropertiesSet();
        }

        // 2. 配置信息 init-method
        String initMethodName = beanDefinition.getInitMethodName();
        if (StrUtil.isNotEmpty(initMethodName)) {
            Method initMethod = beanDefinition.getBeanClass().getMethod(initMethodName);
            if (null == initMethod) {
                throw new BeansException("Could not find an init method named '" + initMethodName + "' on bean with name '" + beanName + "'");
            }
            initMethod.invoke(wrappedBean);
        }
    }

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }

    /**
     * Bean 实例化后对于返回 false 的对象,不再执行后续属性填充操作
     *
     * @param beanName 当前 Bean 的名称
     * @param bean     当前 Bean 实例
     * @return 如果返回 true,则继续填充属性;返回 false,则跳过属性填充
     */
    private boolean applyBeanPostProcessorsAfterInstantiation(String beanName, Object bean) {
        // 默认继续执行属性填充
        boolean continueWithPropertyPopulation = true;

        // 遍历所有注册的 BeanPostProcessor
        for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            // 只处理实现了 InstantiationAwareBeanPostProcessor 的处理器
            if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor instantiationAwareBeanPostProcessor =
                        (InstantiationAwareBeanPostProcessor) beanPostProcessor;

                // 调用 postProcessAfterInstantiation 方法,如果返回 false,就不填充属性
                if (!instantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bean, beanName)) {
                    continueWithPropertyPopulation = false;
                    break; // 一旦有处理器返回 false,立即停止遍历
                }
            }
        }

        // 返回是否继续执行属性填充
        return continueWithPropertyPopulation;
    }


    /*
     * 执行所有注册的 BeanPostProcessor 的 postProcessBeforeInitialization 方法
     * 用于在 Bean 初始化方法执行前,做一些预处理操作
     */
    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (null == current) return result;
            result = current;
        }
        return result;
    }


    /*
     * 执行所有注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法
     * 用于在 Bean 初始化方法执行后,做一些扩展操作(比如 AOP 动态代理等)
     */
    protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
        Constructor constructorToUse = null;
        Class beanClass = beanDefinition.getBeanClass();
        //通过 beanClass.getDeclaredConstructors() 方式可以获取到你所有的构造函数,是一个集合
        Constructor[] declaredConstructors = beanClass.getDeclaredConstructors();

        //循环比对匹配构造函数与args,此处简化为数量对比,实际还需比对入参类型
        for (Constructor ctor : declaredConstructors) {
            if (null != args && ctor.getParameterTypes().length == args.length) {
                constructorToUse = ctor;
                break;
            }
        }

        return getInstantiationStrategy().instantiate(beanDefinition, beanName, constructorToUse, args);
    }

    private void applyPropertyValues(Object bean, String beanName, BeanDefinition beanDefinition) {

        //从beanDefinition得到这个bean的propertyValues。依次注入。如果要注入的属性时另一个bean,就getBean(创建或获取)。
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {

                String name = propertyValue.getName();
                Object value = propertyValue.getValue();

                //instanceof:判断value这个对象是否为BeanReference的实例
                if (value instanceof BeanReference) {

                    // A 依赖 B,获取 B 的实例化
                    BeanReference beanReference = (BeanReference) value;
                    value = getBean(beanReference.getBeanName());
                }

                // 属性填充(BeanUtil是hutool的)
                BeanUtil.setFieldValue(bean, name, value);
            }
        } catch (Exception e) {
            throw new BeansException("Error setting property values:" + beanName,e);
        }
    }

    public InstantiationStrategy getInstantiationStrategy() {
        return instantiationStrategy;
    }

    public void setInstantiationStrategy(InstantiationStrategy instantiationStrategy) {
        this.instantiationStrategy = instantiationStrategy;
    }

    /**
     * 若 Bean 实现了 DisposableBean 或配置了销毁方法,则注册其销毁适配器。
     */
    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
        // 非 Singleton 类型的 Bean 不执行销毁方法
        if (!beanDefinition.isSingleton()) return;

        if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
            // 使用 DisposableBeanAdapter 适配器包装 Bean
            // 适配器实现了 DisposableBean 接口,
            // 这样无论 Bean 是实现接口销毁,还是通过配置销毁方法,
            // 都能统一以 DisposableBean 形式注册到容器,方便统一管理和调用销毁逻辑。
            registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));

        }
    }

    /**
     * 在 Bean 实例化前调用,尝试通过 InstantiationAwareBeanPostProcessor
     * 返回代理对象,若有则跳过默认实例化。
     * 返回非空对象时,还会执行后置初始化处理。
     */
    protected Object resolveBeforeInstantiation(String beanName, BeanDefinition beanDefinition) {
        // 调用所有 InstantiationAwareBeanPostProcessor,尝试返回代理或替代对象
        Object bean = applyBeanPostProcessorBeforeInstantiation(beanDefinition.getBeanClass(), beanName);

        if (bean != null) {
            // 如果前置处理返回了代理对象,继续调用所有 BeanPostProcessor 的
            // postProcessAfterInitialization,保证代理对象完成生命周期的后置处理
            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
        }

        // 返回代理对象(非空)或 null(继续默认实例化)
        return bean;
    }

    /**
     * 遍历所有 BeanPostProcessor,调用实现了 InstantiationAwareBeanPostProcessor
     * 的 postProcessBeforeInstantiation,返回第一个非空结果。
     */
    public Object applyBeanPostProcessorBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 遍历所有注册的 BeanPostProcessor
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 过滤出实现了 InstantiationAwareBeanPostProcessor 的处理器
            if (processor instanceof InstantiationAwareBeanPostProcessor) {
                // 调用 postProcessBeforeInstantiation 方法尝试返回代理对象或替代 Bean
                Object result = ((InstantiationAwareBeanPostProcessor) processor).postProcessBeforeInstantiation(beanClass, beanName);
                // 如果返回非空对象,表示已创建代理或替代对象,直接返回,跳过默认实例化
                if (result != null) return result;
            }
        }
        // 如果所有处理器都未返回代理,返回 null,继续默认实例化流程
        return null;
    }

    /**
     * 在为 Bean 填充属性(依赖注入)之前,允许 BeanPostProcessor 对属性值进行修改。
     *
     * 这里主要是为了支持类似 @Autowired、@Value、@Resource 等注解驱动的依赖注入,
     * 因为它们依赖于 InstantiationAwareBeanPostProcessor 在属性设置前进行解析与赋值。
     *
     * @param beanName        当前 Bean 的名称
     * @param bean            已经实例化好的 Bean 对象(构造方法已调用,但属性还未注入)
     * @param beanDefinition  Bean 对应的定义信息(包含属性、构造参数等)
     */
    protected void applyBeanPostProcessorsBeforeApplyingPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) {

        // 遍历当前容器中注册的所有 BeanPostProcessor
        for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
            // 只有 InstantiationAwareBeanPostProcessor 才能在属性设置前做处理
            if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
                // 调用其 postProcessPropertyValues 方法,让它有机会修改 Bean 的属性值
                // 例如 AutowiredAnnotationBeanPostProcessor 会在这里解析 @Autowired 并生成对应的依赖注入 PropertyValue
                PropertyValues pvs = ((InstantiationAwareBeanPostProcessor) beanPostProcessor)
                        .postProcessPropertyValues(beanDefinition.getPropertyValues(), bean, beanName);

                // 如果处理器返回了新的属性值集合,则合并到 BeanDefinition 的属性列表中
                if (null != pvs) {
                    for (PropertyValue propertyValue : pvs.getPropertyValues()) {
                        beanDefinition.getPropertyValues().addPropertyValue(propertyValue);
                    }
                }
            }
        }
    }
}

3.4AutowiredAnnotationBeanPostProcessor补充实现:

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}

测试:

准备:

新增一个用于循环依赖的类:

@Component
public class TempService {

    @Autowired
    private IUserService userService;

    public void queryUserInfo() {

        String result = userService.queryUserInfo();
        System.out.println("TempService 调用了 userService.queryUserInfo():"+result);
    }

    public void talk() {
        System.out.println("TempService:talk! ");
    }
}

新增方法与属性。注意接口中也要定义方法。

@Component("userService")
public class UserService implements IUserService {

    @Value("${token}")
    private String token;

    @Autowired
    private UserDao userDao;

    @Autowired
    private TempService tempService;

    public String queryUserInfo() {
        try {
            Thread.sleep(new Random(1).nextInt(100));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return userDao.queryUserName("10001") + "," + token;
    }

    public void useTempService() {
        tempService.talk();
    }

    @Override
    public String toString() {
        return "UserService#token = { " + token + " }";
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }
}

xml配置:

与之前相比修改了aop介入点:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean class="com.miniSpring.beans.factory.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:token.properties"/>
    </bean>

    <!-- 自动代理创建器:-->
    <bean class="com.miniSpring.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

    <!-- aop组合1-->
    <bean id="beforeAdvice1" class="com.miniSpring.test.bean.LogBeforeAdvice"/>

    <bean id="methodInterceptor1" class="com.miniSpring.aop.adapter.MethodBeforeAdviceInterceptor">
        <property name="advice" ref="beforeAdvice1"/>
    </bean>

    <bean id="pointcutAdvisor1" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.queryUserInfo(..))"/>
        <property name="advice" ref="methodInterceptor1"/>
        <property name="order" value="3"/>
    </bean>

    <!-- aop组合2-->
    <bean id="afterAdvice2" class="com.miniSpring.test.bean.LogAfterAdvice"/>

    <bean id="methodInterceptor2" class="com.miniSpring.aop.adapter.MethodAfterAdviceInterceptor">
        <property name="advice" ref="afterAdvice2"/>
    </bean>

    <bean id="pointcutAdvisor2" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.queryUserInfo(..))"/>
        <property name="advice" ref="methodInterceptor2"/>
        <property name="order" value="2"/>
    </bean>

    <!-- aop组合3-->
    <bean id="aroundAdvice3" class="com.miniSpring.test.bean.LogAroundAdvice"/>

    <bean id="methodInterceptor3" class="com.miniSpring.aop.adapter.MethodAroundAdviceInterceptor">
        <property name="advice" ref="aroundAdvice3"/>
    </bean>

    <bean id="pointcutAdvisor3" class="com.miniSpring.aop.aspectj.AspectJExpressionPointcutAdvisor">
        <property name="expression" value="execution(* com.miniSpring.test.bean.IUserService.queryUserInfo(..))"/>
        <property name="advice" ref="methodInterceptor3"/>
        <property name="order" value="1"/>
    </bean>


    <component-scan base-package="com.miniSpring.test.bean"/>

<!--    <bean id="tempService" class="com.miniSpring.test.bean.TempService">-->
<!--        <property name="userService" ref="userService"></property>-->
<!--    </bean>-->
</beans>

单元测试:

@Test
    public void test() {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
        IUserService userService = applicationContext.getBean("userService", IUserService.class);
        TempService tempService = (TempService) applicationContext.getBean("tempService");

        tempService.queryUserInfo();
        userService.useTempService();
    }

结果:

环绕通知: 方法 queryUserInfo 执行前
前置通知: 方法 queryUserInfo 即将执行
后置通知: 方法 queryUserInfo 执行完毕, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
环绕通知: 方法 queryUserInfo 执行后, 返回值: CMD137,北京,亦庄,123_TEST_TOKEN_321
TempService 调用了 userService.queryUserInfo():CMD137,北京,亦庄,123_TEST_TOKEN_321
TempService:talk! 

Process finished with exit code 0

可以看到循环依赖问题解决了,aop增强也依然生效。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇