天天看點

Spring循環依賴-spring源碼詳解(四)

上篇文章說了,bean工廠後置處理器如何加載配置類

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,再指派屬性。

public static void main(String[] args) throws Exception {
        // 加載到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;
    }      
Spring循環依賴-spring源碼詳解(四)

這樣寫完之後,就不會有死循環,但是沒有用到二級緩存,二級緩存可以用來放半成品的bean,解決多線程的情況下,多個線程同時建立bean,防止其他線程拿到不完整的bean,于是 加上二級緩存來寫。

private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    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,是以要在之前就建立動态代理。是以這裡有兩個地方調用動态代理,執行個體化之後和初始化之後調用。

隻在循環依賴的情況下在執行個體化之後建立動态代理,是以需要判斷目前是不是循環依賴。

private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    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;
    }