什么是循环依赖
所谓的循环依赖是指,A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。或者是 A 依赖 B,B 依赖 C,C 又依
赖 A。它们之间的依赖关系如下
代码示例:
public class MainStart {private static Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);/*** 读取bean定义,当然在spring中肯定是根据配置 动态扫描注册*/public static void loadBeanDefinitions() {RootBeanDefinition aBeanDefinition=new RootBeanDefinition(InstanceA.class);RootBeanDefinition bBeanDefinition=new RootBeanDefinition(InstanceB.class);beanDefinitionMap.put("instanceA",aBeanDefinition);beanDefinitionMap.put("instanceB",bBeanDefinition);}public static void main(String[] args) throws Exception {// 加载了BeanDefinitionloadBeanDefinitions();// 注册Bean的后置处理器// 循环创建Beanfor (String key : beanDefinitionMap.keySet()){// 先创建AgetBean(key);}InstanceA instanceA = (InstanceA) getBean("instanceA");instanceA.say();}// 一级缓存public static Map<String,Object> singletonObjects=new ConcurrentHashMap<>();// 二级缓存: 为了将 成熟Bean和纯净Bean分离,避免读取到不完整得Beanpublic static Map<String,Object> earlySingletonObjects=new ConcurrentHashMap<>();// 三级缓存public static Map<String,ObjectFactory> singletonFactories=new ConcurrentHashMap<>();// 循环依赖标识public static Set<String> singletonsCurrennlyInCreation=new HashSet<>();// 假设A 使用了Aop @PointCut("execution(* *..InstanceA.*(..))") 要给A创建动态代理// 获取Beanpublic static Object getBean(String beanName) throws Exception {Object singleton = getSingleton(beanName);if(singleton!=null){return singleton;}// 正在创建if(!singletonsCurrennlyInCreation.contains(beanName)){singletonsCurrennlyInCreation.add(beanName);}// createBean// 实例化RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);Class<?> beanClass = beanDefinition.getBeanClass();Object instanceBean = beanClass.newInstance(); // 通过无参构造函数// 创建动态代理 (耦合 、BeanPostProcessor) Spring还是希望正常的Bean 还是再初始化后创建// 只在循环依赖的情况下在实例化后创建proxy 判断当前是不是循环依赖singletonFactories.put(beanName, () -> new JdkProxyBeanPostProcessor().getEarlyBeanReference(earlySingletonObjects.get(beanName),beanName));// 添加到二级缓存// earlySingletonObjects.put(beanName,instanceBean);// 属性赋值Field[] declaredFields = beanClass.getDeclaredFields();for (Field declaredField : declaredFields) {Autowired annotation = declaredField.getAnnotation(Autowired.class);// 说明属性上面有Autowiredif(annotation!=null){declaredField.setAccessible(true);// byname bytype byconstrator// instanceBString name = declaredField.getName();Object fileObject= getBean(name); //拿到B得BeandeclaredField.set(instanceBean,fileObject);}}// 初始化 init-mthod// 放在这里创建已经完了 B里面的A 不是proxy// 正常情况下会再 初始化之后创建proxy// 由于递归完后A 还是原实例,, 所以要从二级缓存中拿到proxy 。if(earlySingletonObjects.containsKey(beanName)){instanceBean=earlySingletonObjects.get(beanName);}// 添加到一级缓存 AsingletonObjects.put(beanName,instanceBean);// remove 二级缓存和三级缓存return instanceBean;}public static Object getSingleton(String beanName){// 先从一级缓存中拿Object bean = singletonObjects.get(beanName);// 说明是循环依赖if(bean==null && singletonsCurrennlyInCreation.contains(beanName)){bean=earlySingletonObjects.get(beanName);// 如果二级缓存没有就从三级缓存中拿if(bean==null) {// 从三级缓存中拿ObjectFactory factory = singletonFactories.get(beanName);if (factory != null) {bean=factory.getObject(); // 拿到动态代理earlySingletonObjects.put(beanName, bean);}}}return bean;}}
总结:getBean()核心方法
1:先实例化化,采用反射无参构造Object beanInstanc = beanClass.newInstance();
2:获取filed 对filed 赋值,递归调用getBean方法Object fileObject= getBean(name);
3:将bean 放到 一级缓存singletonObjects.put(beanName,instanceBean);
如何解决循环依赖
三级缓存
一级缓存
保存的是单实例的beanprivate final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
二级缓存
缓存的是早期对象,不完整的bean对象private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
三级缓存
缓存的是 ObjectFactoryprivate final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
创建的步骤
创建原始 bean 对象
instanceWrapper = createBeanInstance(beanName, mbd, args);final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
暴露早期的引用
把早期对象包装称ObjectFactory 放在三级缓存- 解析依赖
populateBean(beanName, mbd, instanceWrapper);对对象A填充属性B,会调用BeanFactory.getBean(方法 - 获取早期引用
this.earlySingletonObjects.get("beanA")
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
protected Object getSingleton(String beanName, boolean allowEarlyReference) {// Quick check for existing instance without full singleton lock// 从单例对象缓存中获取beanName对应的单例对象Object singletonObject = this.singletonObjects.get(beanName);// 如果单例对象缓存中没有,并且该beanName对应的单例bean正在创建中if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {//从早期单例对象缓存中获取单例对象(之所称成为早期单例对象,是因为earlySingletonObjects里// 的对象的都是通过提前曝光的ObjectFactory创建出来的,还未进行属性填充等操作)singletonObject = this.earlySingletonObjects.get(beanName);// 如果在早期单例对象缓存中也没有,并且允许创建早期单例对象引用if (singletonObject == null && allowEarlyReference) {// 如果为空,则锁定全局变量并进行处理synchronized (this.singletonObjects) {// Consistent creation of early reference within full singleton locksingletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null) {// 当某些方法需要提前初始化的时候则会调用addSingletonFactory方法将对应的ObjectFactory初始化策略存储在singletonFactoriesObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {// 如果存在单例对象工厂,则通过工厂创建一个单例对象singletonObject = singletonFactory.getObject();// 记录在缓存中,二级缓存和三级缓存的对象不能同时存在this.earlySingletonObjects.put(beanName, singletonObject);// 从三级缓存中移除this.singletonFactories.remove(beanName);}}}}}}return singletonObject;}
对应过程的流程图
https://www.processon.com/view/link/5f1fb2cf1e08533a628a7b4c
三级缓存的原因
二级缓存:分离完整bean和初始化bean,多线程下要保证getBean是完整bean
为什么三级:
bean的aop实在初始化之后,
如果循环依赖Bean使用aop,需要提前创建aop
三级缓存,是一个函数接口,代理对象,普通对象都在BeanPostProcessore,可以解耦,
?我在看看吧
spring不能解决构造器的循环依赖:
实例化之前,缓存没有bean的信息,也就取不到
多例不能解决循环依赖:
如果是原型bean: 每次都有创建对象
如果是构造注入,需要调用构造注入,无法利用缓存
循环依赖的关闭功能
public class Main {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();applicationContext.setAllowCircularReferences(false);applicationContext.register(AppConfig.class);applicationContext.refresh();}}
如何扩展
SmartInstantiationAwareBeanPostProcessor 重写 getEarlyBeanReference
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)throws BeanCreationException {//省略其他代码,只保留了关键代码//...// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}//将刚实例化好的bean添加到一级缓存中addSingletonFactory(beanName, new ObjectFactory@Overridepublic Object getObject()throws BeansException {//执行拓展的后置处理器return getEarlyBeanReference(beanName, mbd, bean);}});}}
getEarlyBeanRerence方法
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;//判读我们容器中是否有InstantiationAwareBeanPostProcessors类型的后置处理器if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {//获取我们所有的后置处理器for (BeanPostProcessor bp : getBeanPostProcessors()) {//判断我们的后置处理器是不是实现了SmartInstantiationAwareBeanPostProcessor接口if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {//进行强制转换SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;//挨个调用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReferenceexposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}
扩展实例code
@Componentpublic class TulingBPP implements SmartInstantiationAwareBeanPostProcessor {public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {if(beanName.equals("instanceA") || beanName.equals("instanceB")) {JdkDynimcProxy jdkDynimcProxy = new JdkDynimcProxy(bean);return jdkDynimcProxy.getProxy();}return bean;}}
还得自己多看code
源码入口:
// 初始化剩下的单实例(非懒加载的)
finishBeanFactoryInitialization(beanFactory);
