网站忘了怎么办网站建设优化推广教程
文章目录
- 一、目标:通过三级缓存解决循环依赖
 - 二、设计:通过三级缓存解决循环依赖
 - 2.1 通过三级缓存解决循环依赖
 - 2.2 尝试使用一级缓存解决循环依赖
 
- 三、实现:通过三级缓存解决循环依赖
 - 3.1 工程结构
 - 3.2 通过三级缓存解决循环依赖类图
 - 3.3 设置三级缓存
 - 3.3.1 对象工厂
 - 3.3.2 设置三级缓存
 
- 3.4 提前暴露对象
 - 3.4.1 实例化感知对象处理
 - 3.4.2 默认自动代理创建者
 - 3.4.3 实现默认bean创建的抽象bean工厂超类
 
- 四、测试:通过三级缓存解决循环依赖
 - 4.1 添加测试配置
 - 4.1.1 老公类
 - 4.1.2 媳妇类
 - 4.1.3 婆婆接口
 - 4.1.4 婆婆代理类
 - 4.1.5 切面
 - 4.1.6 Spring属性配置文件
 
- 4.2 单元测试
 
- 五、总结:通过三级缓存解决循环依赖
 
一、目标:通过三级缓存解决循环依赖
💡 如何解决类与类之间的循环依赖?
- 在目前的 Spring 框架中,如果你配置了 
A、B两个 Bean 对象互相依赖,那么立刻会抛出java.lang.StackOverflowError,为什么?- 因为 A 创建时需要依赖 B 创建,而 B 的创建又依赖于 A 创建,就这样死循环了。
 
 - 循环依赖 基本可以说是 Spring 中经典的实现,所要解决的场景主要三种情况。
 

- 循环依赖主要分为三种:自身依赖于自身、互相循环依赖、多组循环依赖。
 - 但无论循环依赖的数量有多少,循环依赖的本质是一样。 
- 就是你的完整创建依赖于我,而我的完整创建也依赖于你,但我们互相没法解耦,最终导致依赖创建失败。
 
 - 所以需要 Spring 提供除了构造函数注入和原型注入外的,
setter循环依赖注入解决方案。 
二、设计:通过三级缓存解决循环依赖
2.1 通过三级缓存解决循环依赖
💡 设计:通过三级缓存解决循环依赖
- 用于解决循环依赖需要用到三个缓存,这三个缓存分别存放: 
成品对象、半成品对象(未填充属性值)、代理对象,分阶段存放对象内容,来解决循环依赖问题。
 - 需要知道核心原理:用于解决循环依赖就必须是三级缓存吗?二级缓存行吗?一级缓存行吗? 
- 其实都能解决。但是 Spring 框架的实现要保证几个事情。如: 
- 只有一级缓存处理流程没法拆分,复杂度也会增加,同时半成品对象可能会有空指针异常。
 - 而将半成品与成品对象分开,处理起来也更加优雅、简单、易扩展。
 
 - 另外 Spring 的两大特性中不仅有 IOC,还有 AOP,也就是基于字节码增强后的方法,该存放到哪。 
- 而三级缓存最主要,要解决的循环依赖就是对 AOP 的处理,但如果把 AOP 代理对象的创建提前,那么二级缓存也一样可以解决。
 - 但是,这就违背了 Spring 创建对象的原则,Spring 更喜欢把所有的普通 Bean 都初始化完成,再处理代理对象的初始化。
 
 
 - 其实都能解决。但是 Spring 框架的实现要保证几个事情。如: 
 - 思考:如果有对象不只是简单的对象,还有代理对象,还有 AOP 应用,要怎么处理这样的依赖问题。
 

- 关于循环依赖在目前的 Spring 框架中,主要就是对于创建的提前暴露。 
- 如果是工厂对象则会使用 
getEarlyBeanReference逻辑提前将工厂对象存放到三级缓存中。 - 等到后续获取对象的时候实际拿到的是工厂对象中 
getObject,这个才是最终的实际对象。 
 - 如果是工厂对象则会使用 
 - 在创建对象的 
AbstractAutowireCapableBeanFactory#doCreateBean方法中,提前暴露对象以后。- 就可以通过接下来的流程,
getSingleton从三个缓存中以此寻找对象。 - 一级、二级如果有则直接取走,如果对象是三级缓存中则会从三级缓存中获取后并删掉工厂对象,把实际对象放到二级缓存中。
 
 - 就可以通过接下来的流程,
 - 最后是关于单例的对象的注册操作,这个注册操作就是把真实的实际对象放到一级缓存中,因为此时它已经是一个成品对象了。
 
2.2 尝试使用一级缓存解决循环依赖

- 如果仅以一级缓存解决循环依赖,那么在实现上可以通过 A 对象 
newInstance创建且未填充属性后,直接放入缓存中。 - 在 A 对象的属性填充 B 对象时,如果缓存中不能获取到 B 对象,则开始创建 B 对象,同样创建完成后,把 B 对象填充到缓存中。
 - 接下来就开始对 B 对象的属性进行填充,恰好这会可以从缓存中拿到半成品的 A 对象,那么这个时候 B 对象的属性就填充完了。
 - 最后返回来继续完成 A 对象的属性填充,把实例化后并填充了属性的 B 对象赋值给 A 对象的 
b属性,这样就完成了一个循环依赖操作。 
CircleTest.java
package com.lino.springframework.test;import java.lang.reflect.Field;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @description: 循环依赖案例*/
public class CircleTest {private final static Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);public static void main(String[] args) throws Exception {System.out.println(getBean(B.class).getA());System.out.println(getBean(A.class).getB());}private static <T> T getBean(Class<T> beanClass) throws Exception {String beanName = beanClass.getSimpleName().toLowerCase();if (singletonObjects.containsKey(beanName)) {return (T) singletonObjects.get(beanName);}// 实例化对象入缓存Object obj = beanClass.newInstance();singletonObjects.put(beanName, obj);// 属性填充补全对象Field[] fields = obj.getClass().getDeclaredFields();for (Field field : fields) {field.setAccessible(true);Class<?> fieldClass = field.getType();String fieldBeanName = fieldClass.getSimpleName().toLowerCase();field.set(obj, singletonObjects.containsKey(fieldBeanName) ? singletonObjects.get(fieldBeanName) : getBean(fieldClass));field.setAccessible(false);}return (T) obj;}
}class A {private B b;public B getB() {return b;}public void setB(B b) {this.b = b;}
}class B {private A a;public A getA() {return a;}public void setA(A a) {this.a = a;}
}
 
测试结果
com.lino.springframework.test.A@266474c2
com.lino.springframework.test.B@6f94fa3e
 

- 从测试效果和截图依赖过程中可以看到,一级缓存也可以解决简单场景的循环依赖问题。
 - 其实 
getBean,是整个解决循环依赖的核心内容,A 创建后填充属性时依赖 B,那么就去创建 B,在创建 B 开始填充时发现依赖于 A,但此时 A 这个半成品对象已经存放在缓存到singletonObjects中了,所以 B 可以正常创建,再通过递归把 A 也创建完整了。 
三、实现:通过三级缓存解决循环依赖
3.1 工程结构
spring-step-16
|-src|-main|	|-java|		|-com.lino.springframework|			|-aop|			|	|-aspectj|			|	|	|-AspectJExpressionPointcut.java|			|	|	|-AspectJExpressionPointcutAdvisor.java|			|	|-framework|			|	|	|-adapter|			|	|	|	|-MethodBeforeAdviceInterceptor.java|			|	|	|-autoproxy|			|	|	|	|-DefaultAdvisorAutoProxyCreator.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|			|	|	|	|-AbstractBeabDefinitionReader.java|			|	|	|	|-AbstractBeabFactory.java|			|	|	|	|-BeabDefinitionReader.java|			|	|	|	|-BeanDefinitionRegistry.java|			|	|	|	|-CglibSubclassingInstantiationStrategy.java|			|	|	|	|-DefaultListableBeanFactory.java|			|	|	|	|-DefaultSingletonBeanRegistry.java|			|	|	|	|-DisposableBeanAdapter.java|			|	|	|	|-FactoryBeanRegistrySupport.java|			|	|	|	|-InstantiationStrategy.java|			|	|	|	|-SimpleInstantiationStrategy.java|			|	|	|-xml|			|	|	|	|-XmlBeanDefinitionReader.java|			|	|	|-Aware.java|			|	|	|-BeanClassLoaderAware.java|			|	|	|-BeanFactory.java|			|	|	|-BeanFactoryAware.java|			|	|	|-BeanNameAware.java|			|	|	|-ConfigurableListableBeanFactory.java|			|	|	|-DisposableBean.java|			|	|	|-FactoryBean.java|			|	|	|-HierarcgicalBeanFactory.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|			|-util|			|	|-ClassUtils.java|			|	|-StringValueResolver.java|-test|-java|-com.lino.springframework.test|-bean|	|-Husband.java|	|-HusbandMother.java|	|-IMother.java|	|-SpouseAdvice.java|	|-Wife.java|-ApiTest.java|-CircleTest.java|-resources|-spring.xml
 
3.2 通过三级缓存解决循环依赖类图

- 循环依赖的黑犀牛功能实现主要包括 
DefaultSingletonBeanRegistry提供三级缓存。singletonObjects、earlySingletonObjects、singletonFactiries,分别存放成品对象、半成品对象和工厂对象。- 同时包装三个缓存提供方法:
getSingleton、registerSingleton、addSingletonFactory,这样使用方就可以分别在不同时间段存放和获取对应的对象。 
 - 在 
AbstractAutowireCapableBeanFactory的doCreateBean方法中,提供了关于提前暴露对象的操作。addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, beanDefinition, finalBean))- 以及后续获取对象和注册对象的操作:
exposedObject = getSingleton(beanName)、registerSingleton(beanName, exposedObject)。 - 经过这样的处理就可以完成对复杂场景循环依赖的操作。
 
 - 另外在 
DefaultAdvisorAutoProxyCreator提供的切面服务中,也需要实现接口InstantiationAwareBeanPostProcessor新增的getEarlyBeanReference方法,便于把依赖的切面对象也能存放到三级缓存中,处理对应的循环依赖。 
3.3 设置三级缓存
3.3.1 对象工厂
ObjectFactory.java
package com.lino.springframework.beans.factory;import com.lino.springframework.beans.BeansException;/*** @description: 对象工厂*/
public interface ObjectFactory<T> {/*** 获取对象** @return 泛型对象* @throws BeansException 异常*/T getObject() throws BeansException;
}
 
3.3.2 设置三级缓存
DefaultSingletonBeanRegistry.java
package com.lino.springframework.beans.factory.support;import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.factory.DisposableBean;
import com.lino.springframework.beans.factory.ObjectFactory;
import com.lino.springframework.beans.factory.config.SingletonBeanRegistry;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;/*** @description: 通用的注册表实现*/
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {protected static final Object NULL_OBJECT = new Object();/*** 一级缓存,普通对象*/private Map<String, Object> singletonObjects = new ConcurrentHashMap<>();/*** 二级缓存,提前暴露对象,没有完全实例化的对象*/protected final Map<String, Object> earlySingletonObjects = new HashMap<>();/*** 三级缓存,存放代理对象*/private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();private final Map<String, DisposableBean> disposableBeans = new HashMap<>();@Overridepublic Object getSingleton(String beanName) {Object singletonObject = singletonObjects.get(beanName);if (null == singletonObject) {singletonObject = earlySingletonObjects.get(beanName);// 判断二级缓存中是否有对象,这个对象就是代理对象,因为只有代理对象才会放到三级缓存中if (null == singletonObject) {ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();// 把三级缓存中的代理对象中的真实对象获取出来,放入二级缓存中earlySingletonObjects.put(beanName, singletonObject);singletonFactories.remove(beanName);}}}return singletonObject;}@Overridepublic void registerSingletonBean(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)) {this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);}}public void registerDisposableBean(String beanName, DisposableBean bean) {disposableBeans.put(beanName, bean);}public void destroySingletons() {Set<String> keySet = this.disposableBeans.keySet();Object[] disposableBeanNames = keySet.toArray();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);}}}
}
 
- 在用于提供单例对象注册操作的 
DefaultSingletonBeanRegistry类中,共有三个缓存对象的属性:singletonObjects、earlySingletonObjects、singletonFactories。- 用于存放不同类型的对象:单例对象、早期的半成品单例对象、单例工厂对象。
 
 - 紧接着在这三个缓存对象下提供了获取、添加和注册不同对象的方法,包括:
getSingleton、registerSingletonBean、addSingletonFactory。- 后面的两个方法都比较简单,主要是 
getSingleton的操作,它是一层层处理不同时期的单例对象,直至拿到有效的对象。 
 - 后面的两个方法都比较简单,主要是 
 
3.4 提前暴露对象
3.4.1 实例化感知对象处理
InstantiationAwareBeanPostProcessor.java
package com.lino.springframework.beans.factory.config;import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValues;/*** @description: 实例化感知对象处理*/
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {.../*** 在 Spring 中由 SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference 提供** @param bean     对象* @param beanName 对象名称* @return 二级缓存对象*/default Object getEarlyBeanReference(Object bean, String beanName) {return bean;}
}
 
- 添加 
getEarlyBeanReference缓存二级缓存对象方法 
3.4.2 默认自动代理创建者
DefaultAdvisorAutoProxyCreator.java
package com.lino.springframework.aop.framework.autoproxy;import com.lino.springframework.aop.*;
import com.lino.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import com.lino.springframework.aop.framework.ProxyFactory;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.BeanFactory;
import com.lino.springframework.beans.factory.BeanFactoryAware;
import com.lino.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import com.lino.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;/*** @description: 默认自动代理创建者*/
public class DefaultAdvisorAutoProxyCreator implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {private DefaultListableBeanFactory beanFactory;private final Set<Object> earlyProxyReferences = Collections.synchronizedSet(new HashSet<>());@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {this.beanFactory = (DefaultListableBeanFactory) beanFactory;}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}private boolean isInfrastructureClass(Class<?> beanClass) {return Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (!earlyProxyReferences.contains(beanName)) {return wrapIfNecessary(bean, beanName);}return bean;}protected Object wrapIfNecessary(Object bean, String beanName) {if (isInfrastructureClass(bean.getClass())) {return bean;}Collection<AspectJExpressionPointcutAdvisor> advisors = beanFactory.getBeansOfType(AspectJExpressionPointcutAdvisor.class).values();for (AspectJExpressionPointcutAdvisor advisor : advisors) {ClassFilter classFilter = advisor.getPointcut().getClassFilter();// 过滤匹配类if (!classFilter.matches(bean.getClass())) {continue;}AdvisedSupport advisedSupport = new AdvisedSupport();TargetSource targetSource = new TargetSource(bean);advisedSupport.setTargetSource(targetSource);advisedSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());advisedSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());advisedSupport.setProxyTargetClass(true);// 返回代理对象return new ProxyFactory(advisedSupport).getProxy();}return bean;}@Overridepublic Object getEarlyBeanReference(Object bean, String beanName) {earlyProxyReferences.add(beanName);return wrapIfNecessary(bean, beanName);}@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {return pvs;}
}
 
3.4.3 实现默认bean创建的抽象bean工厂超类
AbstractAutowireCapableBeanFactory.java
package com.lino.springframework.beans.factory.support;import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.lino.springframework.beans.BeansException;
import com.lino.springframework.beans.PropertyValue;
import com.lino.springframework.beans.PropertyValues;
import com.lino.springframework.beans.factory.*;
import com.lino.springframework.beans.factory.config.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;/*** @description: 实现默认bean创建的抽象bean工厂超类*/
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {private InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy();@Overrideprotected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws BeansException {// 判断是否返回代理 Bean 对象Object bean = resolveBeforeInstantiation(beanName, beanDefinition);if (null != bean) {return bean;}return doCreateBean(beanName, beanDefinition, args);}protected Object doCreateBean(String beanName, BeanDefinition beanDefinition, Object[] args) {Object bean = null;try {// 实例化Beanbean = createBeanInstance(beanDefinition, beanName, args);// 处理循环依赖,将实例化后的Bean对象提前放入缓存中暴露出来if (beanDefinition.isSingleton()) {Object finalBean = bean;addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, beanDefinition, finalBean));}// 实例化后判断boolean continueWithPropertyPopulation = applyBeanPostProcessorsAfterInstantiation(beanName, bean);if (!continueWithPropertyPopulation) {return bean;}// 在设置Bean属性之前,允许 BeanPostProcessor修改属性值applyBeanPostProcessorsBeforeApplyingPropertyValues(beanName, bean, beanDefinition);// 给bean填充属性applyPropertyValues(beanName, bean, beanDefinition);// 执行 Bean 的初始化方法和 BeanPostProcessor 的前置和后置处理方法bean = initializeBean(beanName, bean, beanDefinition);} catch (Exception e) {throw new BeansException("Instantiation of bean failed", e);}// 注册实现 DisposableBean 接口的 Bean 对象registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);// 判断 SCOPE_SINGLETON、SCOPE_PROTOTYPEObject exposedObject = bean;if (beanDefinition.isSingleton()) {// 获取代理对象exposedObject = getSingleton(beanName);registerSingletonBean(beanName, exposedObject);}return exposedObject;}protected Object getEarlyBeanReference(String beanName, BeanDefinition beanDefinition, Object bean) {Object exposedObject = bean;for (BeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {exposedObject = ((InstantiationAwareBeanPostProcessor) beanPostProcessor).getEarlyBeanReference(exposedObject, beanName);if (null == exposedObject) {return exposedObject;}}}return exposedObject;}...
}
 
- 在 
AbstractAutowireCapableBeanFactory#doCreateBean的方法中主要是扩展了对象的提前暴露addSingletonFactory,和单例对象的获取getSingleton,以及注册操作registerSingletonBean。 getEarlyBeanReference方法就是定义在如 AOP 切面中这样的代理对象。
四、测试:通过三级缓存解决循环依赖
4.1 添加测试配置
4.1.1 老公类
Husband.java
package com.lino.springframework.test.bean;/*** @description: 老公类*/
public class Husband {private Wife wife;public String queryWife() {return "Husband.wife";}public Wife getWife() {return wife;}public void setWife(Wife wife) {this.wife = wife;}
}
 
4.1.2 媳妇类
Wife.java
package com.lino.springframework.test.bean;/*** @description: 媳妇类*/
public class Wife {private Husband husband;private IMother mother;public String queryHusband() {return "Wife.husband、Mother.callMother: " + mother.callMother();}public Husband getHusband() {return husband;}public void setHusband(Husband husband) {this.husband = husband;}public IMother getMother() {return mother;}public void setMother(IMother mother) {this.mother = mother;}
}
 
4.1.3 婆婆接口
IMother.java
package com.lino.springframework.test.bean;/*** @description: 婆婆接口*/
public interface IMother {String callMother();
}
 
4.1.4 婆婆代理类
HusbandMother.java
package com.lino.springframework.test.bean;import com.lino.springframework.beans.factory.FactoryBean;
import java.lang.reflect.Proxy;/*** @description: 老公婆婆类*/
public class HusbandMother implements FactoryBean<IMother> {@Overridepublic IMother getObject() throws Exception {return (IMother) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{IMother.class},(proxy, method, args) -> "婚后媳妇妈妈的职责被婆婆代理了!" + method.getName());}@Overridepublic Class<?> getObjectType() {return IMother.class;}@Overridepublic boolean isSingleton() {return true;}
}
 
4.1.5 切面
SpouseAdvice.java
package com.lino.springframework.test.bean;import com.lino.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;/*** @description: 拦截器*/
public class SpouseAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("关怀小两口(切面):" + method);}
}
 
4.1.6 Spring属性配置文件
spring.xml
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="husband" class="com.lino.springframework.test.bean.Husband"><property name="wife" ref="wife"/></bean><bean id="husbandMother" class="com.lino.springframework.test.bean.HusbandMother"/><bean id="wife" class="com.lino.springframework.test.bean.Wife"><property name="husband" ref="husband"/><property name="mother" ref="husbandMother"/></bean><!--AOP 配置,验证三级缓存    --><bean class="com.lino.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/><bean id="beforeAdvice" class="com.lino.springframework.test.bean.SpouseAdvice"/><bean id="methodInterceptor" class="com.lino.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor"><property name="advice" ref="beforeAdvice"/></bean><bean id="pointcutAdvisor" class="com.lino.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor"><property name="expression" value="execution(* com.lino.springframework.test.bean.Wife.*(..))"/><property name="advice" ref="methodInterceptor"/></bean></beans>
 
4.2 单元测试
ApiTest.java
@Test
public void test_autoProxy() {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");Husband husband = applicationContext.getBean("husband", Husband.class);Wife wife = applicationContext.getBean("wife", Wife.class);System.out.println("老公的媳妇:" + husband.queryWife());System.out.println("媳妇的老公:" + wife.queryHusband());
}
 
测试结果
老公的媳妇:Husband.wife
关怀小两口(切面):public java.lang.String com.lino.springframework.test.bean.Wife.queryHusband()
媳妇的老公:Wife.husband、Mother.callMother: 婚后媳妇妈妈的职责被婆婆代理了!callMother
 

- 测试结果看,无论是简单对象依赖,还是代理工程对象,或者 AOP 切面对象,都可以在三级缓存下解决循环依赖的问题。
 - 此外从运行截图 
DefaultSingletonBeanRegistry#getSingleton中也可以看到需要三级缓存存放工厂对象的类,都会使用到getObject获取真实对象,并随后存入半成品对象earlySingletonObjects中以及移除工厂对象。 
五、总结:通过三级缓存解决循环依赖
- Spring 中所有的功能都是以解决 Java 编程中的特性而存在的,就像我们处理的循环依赖,如果没有 Spring 框架的情况下,可能我们也会尽可能避免写出循环依赖的操作,因为在没有经过加工处理后,这样的依赖关系肯定会报错的。 
- 这也是程序从 能用 到 好用 的升级。
 
 - 在解决循环依赖的核心流程中,主要是提前暴露对象的设计,以及建立三级缓存的数据结构来存放不同时期的对象。 
- 如果说没有如切面和工厂中的代理对象,那么二级缓存也就可以解决了,哪怕是只有一级缓存。
 - 但为了设计上的合理和可扩展性,所以创建了三级缓存来放置不同时期的对象。
 
 
