Spring循环依赖-spring源码详解(四)

简介: Spring循环依赖-spring源码详解(四)
 public static void loadBeanDefinitions() {
        RootBeanDefinition rootBeanDefinitionA = new RootBeanDefinition(InstanceA.class);
        RootBeanDefinition rootBeanDefinitionB = new RootBeanDefinition(InstanceB.class);
        beanDefinitionMap.put("instanceA", rootBeanDefinitionA);
        beanDefinitionMap.put("instanceB", rootBeanDefinitionB);
    }

@Component
public class InstanceA {
    @Autowired
    private InstanceB instanceB;

    public InstanceB getInstanceB() {
        return instanceB;
    }

    public void setInstanceB(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    public InstanceA(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    public InstanceA() {
        System.out.println("实例化A");
    }
}

首先把bean放入beanDefinition,之后,循环bean定义,通过bean的key来获取beanDefinition,

通过无参构造函数反射来获取class,再赋值属性。

        // 加载到beanDefinition
        loadBeanDefinitions();

        for (String key : beanDefinitionMap.keySet()) {
            // 先创建A
            getBean(key);
        }
        InstanceA instanceA = (InstanceA)getBean("instanceA");
        System.out.println(instanceA);
    }

    private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();

    public static Object getBean(String beanName) throws Exception {
        Object singleton = getSingleton(beanName);
        if(singleton != null){
            return singleton;
        }

        // 实例化
        RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
        Class<?> beanClass = rootBeanDefinition.getBeanClass();
        // 通过class 无参构造函数 实例化
        Object instanceBean = beanClass.newInstance();

        singletonObjects.put(beanName, instanceBean);
        // 属性赋值
        Field[] declaredFields = beanClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            Autowired annotation = declaredField.getAnnotation(Autowired.class);
            // 说明bean有autowired
            if (annotation != null) {
                // 打开访问权限
                declaredField.setAccessible(true);
                // byName  byType   拿到了 instanceB名字
                String name = declaredField.getName();
                // 拿到B的bean
                Object fileObject = getBean(name);
                declaredField.set(instanceBean, fileObject);
            }
        }
        // 初始化
        // 放入缓存
//        singletonObjects.put(beanName, instanceBean);
        return instanceBean;
    }

    private static Object getSingleton(String beanName) {
        Object singleton = singletonObjects.get(beanName);
        if (singleton != null) {
            return singleton;
        }
        return null;
    }

image.png

这样写完之后,就不会有死循环,但是没有用到二级缓存,二级缓存可以用来放半成品的bean,解决多线程的情况下,多个线程同时创建bean,防止其他线程拿到不完整的bean,于是 加上二级缓存来写。

   private static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();

   public static Object getBean(String beanName) throws Exception {
       Object singleton = getSingleton(beanName);
       if (singleton != null) {
           return singleton;
       }

       // 实例化
       RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
       Class<?> beanClass = rootBeanDefinition.getBeanClass();
       // 通过class 无参构造函数 实例化
       Object instanceBean = beanClass.newInstance();

       // 二级缓存
       earlySingletonObjects.put(beanName, instanceBean);
       // 属性赋值
       Field[] declaredFields = beanClass.getDeclaredFields();
       for (Field declaredField : declaredFields) {
           Autowired annotation = declaredField.getAnnotation(Autowired.class);
           // 说明bean有autowired
           if (annotation != null) {
               // 打开访问权限
               declaredField.setAccessible(true);
               // byName  byType   拿到了 instanceB名字
               String name = declaredField.getName();
               // 拿到B的bean
               Object fileObject = getBean(name);
               declaredField.set(instanceBean, fileObject);
           }
       }
       // 初始化
       // 放入缓存
       singletonObjects.put(beanName, instanceBean);
       return instanceBean;
   }

   private static Object getSingleton(String beanName) {
       Object singleton = singletonObjects.get(beanName);
       if (singleton != null) {
           return singleton;
       }
       Object earlySingleton = earlySingletonObjects.get(beanName);
       if (earlySingleton != null) {
           return earlySingleton;
       }
       return null;
   }

用解耦的方式,beanPostProcessor来创建动态代理。

如果在最后调用动态代理,这时候循环依赖的bean就不是动态代理的bean,所以要在之前就创建动态代理。所以这里有两个地方调用动态代理,实例化之后和初始化之后调用。

只在循环依赖的情况下在实例化之后创建动态代理,所以需要判断当前是不是循环依赖。
前面一级缓存中没拿到,而二级缓存中有,才是循环依赖。

而spring源码里有一行代码,用来判断是否是循环依赖,加了一个正在创建对象的标识。

   private static Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>();
   // 存放函数接口
   private static Map<String, ObjectFactory> singletonFactories = new ConcurrentHashMap<>();

   private static Set<String> singletonCurrennlyInCreation = new HashSet<>();

   public static Object getBean(String beanName) throws Exception {
       Object singleton = getSingleton(beanName);
       if (singleton != null) {
           return singleton;
       }

       // 正在创建
       if (!singletonCurrennlyInCreation.contains(beanName)) {
           singletonCurrennlyInCreation.add(beanName);
       }

       // 实例化
       RootBeanDefinition rootBeanDefinition = (RootBeanDefinition) beanDefinitionMap.get(beanName);
       Class<?> beanClass = rootBeanDefinition.getBeanClass();
       // 通过class 无参构造函数 实例化
       Object instanceBean = beanClass.newInstance();

       // 创建动态代理
       // 只在循环依赖的情况下在实例化之后创建动态代理
       //Object o = new JDKProxyBeanPostProcessor().getEarlyBeanReference(instanceBean,beanName);
       /*singletonFactories.put(beanName, new ObjectFactory() {
           @Override
           public Object getObject() throws BeansException {
               return  new JDKProxyBeanPostProcessor().getEarlyBeanReference(instanceBean,beanName);
           }
       });*/
       singletonFactories.put(beanName, () -> new JDKProxyBeanPostProcessor().getEarlyBeanReference(instanceBean, beanName));

       // 二级缓存
       //earlySingletonObjects.put(beanName, instanceBean);
       // 属性赋值
       Field[] declaredFields = beanClass.getDeclaredFields();
       for (Field declaredField : declaredFields) {
           Autowired annotation = declaredField.getAnnotation(Autowired.class);
           // 说明bean有autowired
           if (annotation != null) {
               // 打开访问权限
               declaredField.setAccessible(true);
               // byName  byType   拿到了 instanceB名字
               String name = declaredField.getName();
               // 拿到B的bean
               Object fileObject = getBean(name);
               declaredField.set(instanceBean, fileObject);
           }
       }
       // 初始化


       /*if(earlySingletonObjects.containsKey(beanName)){
           instanceBean = earlySingletonObjects.get(beanName);
       }*/
       // 放入缓存
       singletonObjects.put(beanName, instanceBean);
       return instanceBean;
   }

   private static Object getSingleton(String beanName) {
     /*  Object singleton = singletonObjects.get(beanName);
       if (singleton != null) {
           return singleton;
       }
       Object earlySingleton = earlySingletonObjects.get(beanName);
       if (earlySingleton != null) {

           return earlySingleton;
       }
       return null;*/
       Object bean = singletonObjects.get(beanName);
       if (bean == null && singletonCurrennlyInCreation.contains(beanName)) {
           // 是循环依赖
           bean  = earlySingletonObjects.get(beanName);
           synchronized (singletonObjects){
               if(bean == null){
                   ObjectFactory objectFactory = singletonFactories.get(beanName);
                   if (objectFactory != null) {
                       // 钩子函数 去创建 aop代理
                       bean = objectFactory.getObject();
                       earlySingletonObjects.put(beanName, bean);
                       singletonFactories.remove(beanName);
                   }
                   return bean;
               }
           }
       }
       return bean;
   }

相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
1月前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
1月前
|
缓存 架构师 Java
图解 Spring 循环依赖,一文吃透!
Spring 循环依赖如何解决,是大厂面试高频,本文详细解析,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
图解 Spring 循环依赖,一文吃透!
|
16天前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
38 2
|
1月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
63 9
|
2月前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
146 5
|
2月前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
2月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
144 9
|
2月前
|
设计模式 JavaScript Java
Spring 事件监听机制源码
Spring 提供了事件发布订阅机制,广泛应用于项目中。本文介绍了如何通过自定义事件类、订阅类和发布类实现这一机制,并展示了如何监听 SpringBoot 启动过程中的多个事件(如 `ApplicationStartingEvent`、`ApplicationEnvironmentPreparedEvent` 等)。通过掌握这些事件,可以更好地理解 SpringBoot 的启动流程。示例代码展示了从事件发布到接收的完整过程。
|
2月前
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
69 1