手寫Spring之BeanFactory(三級(jí)緩存)

概述

看了好久spring源碼,有些地方理解的不深刻,決定手寫一下BeanFactory來加深理解

規(guī)范

spring中最主要的bean工廠實(shí)現(xiàn)就是DefaultListableBeanFactory,看一下它實(shí)現(xiàn)的接口

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable

主要實(shí)現(xiàn)兩個(gè)接口ConfigurableListableBeanFactoryBeanDefinitionRegistry,下面分別整理下這兩個(gè)接口要實(shí)現(xiàn)的方法

BeanDefinitionRegistry

這個(gè)簡單,從字面理解就是一個(gè)bean定義的注冊(cè)器,那自然可以填加,也可以獲取bean定義
重點(diǎn)方法:

  • void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
    這就是注冊(cè)bean定義
  • BeanDefinition getBeanDefinition(String beanName)
    獲取bean定義

總結(jié)就是,作為一個(gè)bean定義注冊(cè)器,需要實(shí)現(xiàn)可以注冊(cè),完事也可以獲取,一句話概括就是一個(gè)bean定義存儲(chǔ)的容器

ConfigurableListableBeanFactory

這個(gè)相對(duì)復(fù)雜,字面理解是一個(gè)可配置可列出的bean工廠
重點(diǎn)方法(包含了父接口):

  • Object getBean(String name)
    獲取bean,最主要的方法,bean工廠嗎,當(dāng)然主要的任務(wù)就是能獲取bean(當(dāng)然沒有則創(chuàng)建)
  • void preInstantiateSingletons()
    預(yù)初始化所有單例bean(當(dāng)然是根據(jù)注冊(cè)的bean定義來初始化)

SingletonBeanRegistry

這個(gè)倒不是bean工廠的接口,而是DefaultListableBeanFactory的子類DefaultSingletonBeanRegistry實(shí)現(xiàn)的接口

DefaultListableBeanFactory

看名字就知道這是一個(gè)存儲(chǔ)單例bean的容器,著名的三級(jí)緩存就在這里

  • void registerSingleton(String beanName, Object singletonObject)
    注冊(cè)單例對(duì)象
  • Object getSingleton(String beanName)
    獲取單例對(duì)象

也就是他是一個(gè)對(duì)象存儲(chǔ)的容器,就像一個(gè)hashmap

總結(jié)

也就是說DefaultListableBeanFactory是一個(gè)bean工廠,可以獲取bean,可以提前初始化所有bean,同時(shí)它也是一個(gè)bean定義的容器。
而他的bean實(shí)際存儲(chǔ)就是交給他的子類DefaultSingletonBeanRegistry處理的

BeanFactory

實(shí)現(xiàn)

之所以研究DefaultSingletonBeanRegistry的骨架,是為了模仿,因?yàn)槭謱懩7伦詈玫酶3窒嗤囊?guī)范和設(shè)計(jì)思路,要不回頭看源碼還是看不懂
所以我的實(shí)現(xiàn)思路也是首先要實(shí)現(xiàn)兩個(gè)接口,然后按照他的bean存儲(chǔ)方式,也寫個(gè)singletonBeanRegistry用來繼承

<u>注:以下所有代碼由于繼承了spring的接口,所有要有很多實(shí)現(xiàn)方法,只貼了重點(diǎn)實(shí)現(xiàn)的方法,其它方法全默認(rèn)</u>

一.簡單的bean工廠

先考慮最簡單的實(shí)現(xiàn)方式,兩個(gè)容器兩個(gè)hashMap完全可以實(shí)現(xiàn),那就試一下
原來的spring的bean定義有點(diǎn)復(fù)雜,不在本屆的討論范圍,所以自己實(shí)現(xiàn)了個(gè)簡單的bean定義(只存儲(chǔ)類的信息)

public class MyBeanDefinition implements BeanDefinition {
    // 存儲(chǔ)class
    private Class<?> beanClass;
    
    // 簡單的bean定義,只存儲(chǔ)class信息
    public MyBeanDefinition(Class<?> beanClass) {
        this.beanClass = beanClass;
    }

    public Class<?> getBeanClass() {
        return beanClass;
    }

一個(gè)簡單的bean定義實(shí)現(xiàn)了,下面實(shí)現(xiàn)bean工廠,首先實(shí)現(xiàn)一個(gè)bean的容器

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** bean容器,一級(jí)緩存 **/
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** 添加bean **/
    @Override
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        this.singletonObjects.put(beanName, singletonObject);
    }

    /** 獲取bean **/
    @Override
    public Object getSingleton(String beanName) {
        return this.singletonObjects.get(beanName);
    }

其實(shí)就是一個(gè)HashMap包裝成一個(gè)類

實(shí)現(xiàn)BeanFactory

public class MyBeanFactory extends MySingletonBeanRegistry implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {

    /** bean定義容器 **/
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    /**
     * 注冊(cè)bean定義
     */
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        beanDefinitionMap.put(beanName, beanDefinition);
    }

    /**
     * 獲取bean定義
     */
    @Override
    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        return this.beanDefinitionMap.get(beanName);
    }

    /**
     * 提前初始化所有bean
     * @throws BeansException
     */
    @Override
    public void preInstantiateSingletons() throws BeansException {
        // 循環(huán)所有bean定義
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            // 生產(chǎn)bean
            getBean(entry.getKey());
        }
    }

    /**
     * 獲取bean
     */
    @Override
    public Object getBean(String name) throws BeansException {
        try {
            // 先去容器里拿
            Object singleton = getSingleton(name);
            // 如果沒有就創(chuàng)建
            if (singleton==null) {
                // 獲取bean定義
                MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
                // 實(shí)例化bean
                singleton = beanDefinition.getBeanClass().newInstance();
                // 注冊(cè)到容器
                registerSingleton(name, singleton);
            }
            return singleton;
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
    }

就這么簡單實(shí)現(xiàn)了,bean定義容器也是一個(gè)map,getBean就拿到class放射成實(shí)例就行了,測試一下
新建兩個(gè)測試對(duì)象

public class BeanA {     
   public String aName = "A";
}
public class BeanB {     
   public String bName = "B";
}

測試:

System.out.println("===factory1===");
MyBeanFactory1 myBeanFactory1 = new MyBeanFactory1();
myBeanFactory1.registerBeanDefinition("BeanA", new MyBeanDefinition(BeanA.class));
myBeanFactory1.preInstantiateSingletons();
Object a1 = myBeanFactory1.getBean("BeanA");
System.out.println(a1);

輸出

===factory===
{"A":{"aName":"A"}}

完全沒問題

依賴注入

很顯然,一中的實(shí)現(xiàn)最簡單,但如果需要依賴注入,它就做不到了,那么如何實(shí)現(xiàn)依賴注入?
spring依賴注入需要一個(gè)注解@Autowired,我們也寫一個(gè)注解MyAutowired

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAutowired {
}

這時(shí),兩個(gè)對(duì)象修改這樣

public class BeanA {
    public String aName = "A";
         // 想通過依賴注入進(jìn)beanB
    @MyAutowired
    public BeanB beanB;

    @Override
    @AopToString
    public String toString() {
        return "{\"A\":{"
                + "\"aName\":\""
                + aName + '\"'
                + ",\"b\":"
                + (null==beanB?"null":beanB.bName)
                + "}}";

    }
}
public class BeanB {
    
    public String bName = "B";

    @Override
    @AopToString
    public String toString() {
        return "{\"B\":{"
                + "\"bName\":\""
                + bName + "}}";

    }
}

實(shí)現(xiàn)起來也不難,思路如下:
實(shí)例化對(duì)象后,循環(huán)所有屬性,發(fā)現(xiàn)@MyAutowired,調(diào)用getBean("屬性名")獲取另一個(gè)bean,再給屬性賦值,只需修改getBean方法即可

/**
 * 獲取bean
 */
@Override
public Object getBean(String name) throws BeansException {
    try {
        // 先去容器里拿
        Object singleton = getSingleton(name);
        // 如果沒有就創(chuàng)建
        if (singleton==null) {
            // 獲取bean定義
            MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
            // 實(shí)例化bean
            singleton = beanDefinition.getBeanClass().newInstance();
            // 填充屬性(新增)
            popular(singleton, beanDefinition.getBeanClass());
            // 注冊(cè)到容器
            registerSingleton(name, singleton);
        }
        return singleton;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}

實(shí)例化完,新增了個(gè)填充屬性popular方法
實(shí)現(xiàn)如下

private void popular(Object singleton, Class<?> clazz) {
    // 循環(huán)屬性
    for (Field declaredField : clazz.getDeclaredFields()) {
        // 看看是否有MyAutowired注解
        MyAutowired annotation = declaredField.getAnnotation(MyAutowired.class);
        if (annotation!=null) {
            declaredField.setAccessible(true);
            try {
                // 屬性賦值
                declaredField.set(singleton, getBean(declaredField.getType().getSimpleName()));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

流程是這樣的
1.實(shí)例化A
2.循環(huán)A屬性
3.發(fā)現(xiàn)需要B
4.實(shí)例化B
5.將實(shí)例化的B賦值給A對(duì)象的屬性
總之就是A要等B創(chuàng)建完,A才能創(chuàng)建完
測試一下原測試方法,輸出

===factory===
{"A":{"aName":"A","b":B}}

可以看到實(shí)現(xiàn)了,依賴注入

循環(huán)依賴

上文解決了依賴注入,但沒有辦法解決循環(huán)依賴,比如

public class BeanA {
    public String aName = "A";
         // 想通過依賴注入進(jìn)beanB
    @MyAutowired
    public BeanB beanB;

    @Override
    @AopToString
    public String toString() {
        return "{\"A\":{"
                + "\"aName\":\""
                + aName + '\"'
                + ",\"b\":"
                + (null==beanB?"null":beanB.bName)
                + "}}";

    }
}
public class BeanB {
    
    public String bName = "B";

    @MyAutowired
    public BeanA beanA;

    @Override
    public String toString() {
        return "{\"BeanB\":{"
                + "\"bName\":\""
                + bName + '\"'
                + ",\"beanA\":"
                + (null==beanA?"null":beanA.aName)
                + "}}";

    }
}

這時(shí)候A不光需要B,B也需要A,如果還按照上面的方法那么A要等B創(chuàng)建完,B又要等A創(chuàng)建完,那就永遠(yuǎn)不會(huì)創(chuàng)建出來了,死循環(huán),最終StackOverflowError

  • 解決思路1
    方案:preInstantiateSingletons方法先實(shí)例化所有bean并存入一級(jí)緩存,然后所有bean再循環(huán)填充屬性,而getBean只是從bean容器獲取,沒有創(chuàng)建功能
    問題:這樣做完全可以解決循環(huán)依賴,我當(dāng)時(shí)想到的解法就是這樣,但是spring沒這么做,原因其實(shí)也很簡單,這樣做只適合同時(shí)初始化所有bean,但preInstantiateSingletons方法只是實(shí)例化非懶漢模式的單例bean,但因?yàn)閼屑虞d的存在,要求getBean方法必須獲取完整的bean對(duì)象,這種解法就完全行不通
  • 解決思路2
    方案:實(shí)例化后馬上存入一級(jí)緩存,然后再去填充屬性,這樣先A后B的話,先實(shí)例化A,存入一級(jí)緩存,A填充屬性,實(shí)例化B,B存入一級(jí)緩存,B填充屬性,需要A而且一級(jí)緩存有,直接獲取填充B,回到A的getBean再給A的b屬性賦值
    問題:這種方案也可以解決循環(huán)依賴,但是會(huì)出現(xiàn)一個(gè)問題,bean在實(shí)例化時(shí)就已經(jīng)放入一級(jí)緩存,這時(shí)候的bean是一個(gè)不完整的bean,如果被獲取到很容易出問題
  • 解決思路3
    方案:在2的基礎(chǔ)上做優(yōu)化,再添加一層緩存,名曰“二級(jí)緩存”(存放不完整的bean),實(shí)例化的bean先放入二級(jí)緩存并標(biāo)志正在創(chuàng)建,獲取單例對(duì)象時(shí),如果正在創(chuàng)建則從二級(jí)緩存取bean做屬性填充,最后完整的bean存入一級(jí)緩存
    問題:無,這就是spring的解決思路

解決方案已出,下面寫代碼,首先bean容器MySingletonBeanRegistry需要加入二級(jí)緩存,并加入是否正在創(chuàng)建標(biāo)識(shí)功能

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** bean容器,一級(jí)緩存 **/
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** bean容器,二級(jí)緩存 **/
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    /** 存儲(chǔ)正在創(chuàng)建的bean **/
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /**
     * 查看bean是否正在創(chuàng)建
     */
    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }

    /**
     * 標(biāo)志bean正在創(chuàng)建
     */
    protected void beforeSingletonCreation(String beanName) {
        this.singletonsCurrentlyInCreation.add(beanName);
    }

    /**
     * 標(biāo)志bean創(chuàng)建完成
     */
    protected void afterSingletonCreation(String beanName) {
        this.singletonsCurrentlyInCreation.remove(beanName);
    }

    /**
     * 添加bean二級(jí)緩存
     */
    protected void addEarly(String beanName, Object singletonObject) {
        this.earlySingletonObjects.put(beanName, singletonObject);
    }

    /** 添加bean **/
    @Override
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        this.singletonObjects.put(beanName, singletonObject);
    }

    /** 獲取bean **/
    @Override
    public Object getSingleton(String beanName) {
        // 一級(jí)緩存拿
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果拿不到并且正在創(chuàng)建,去二級(jí)緩存拿
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
        }
        return singletonObject;
    }

而BeanFactory需要做的修改,就是getBean 標(biāo)記(改)

/**
 * 獲取bean
 */
@Override
public Object getBean(String name) throws BeansException {
    try {
        // 先去容器里拿
        Object singleton = getSingleton(name);
        // 如果沒有就創(chuàng)建
        if (singleton==null) {
            // 標(biāo)記正在創(chuàng)建(改)
            beforeSingletonCreation(name);
            // 獲取bean定義
            MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
            // 實(shí)例化bean
            singleton = beanDefinition.getBeanClass().newInstance();
            // 提前暴露加到二級(jí)緩存(改)
            addEarly(name, singleton);
            // 填充屬性
            popular(singleton, beanDefinition.getBeanClass());
            // 注冊(cè)到容器
            registerSingleton(name, singleton);
            // 標(biāo)記創(chuàng)建完成(改)
            afterSingletonCreation(name);
        }
        return singleton;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}

測試一下

System.out.println("===factory===");
MyBeanFactory myBeanFactory = new MyBeanFactory();
myBeanFactory.registerBeanDefinition("BeanA", new MyBeanDefinition(BeanA.class));
myBeanFactory.registerBeanDefinition("BeanB", new MyBeanDefinition(BeanB.class));
myBeanFactory.preInstantiateSingletons();
Object a = myBeanFactory.getBean("BeanA");
Object b = myBeanFactory.getBean("BeanB");
System.out.println(a);
System.out.println(b);

輸出

{"A":{"aName":"A","b":B}}
{"B":{"bName":"B","a":A}}

徹底解決了循環(huán)依賴

網(wǎng)上人都說二級(jí)緩存是為了解決循環(huán)依賴,實(shí)際上二級(jí)緩存是為了解決循環(huán)依賴造成的bean不完整問題

代理

解決了循環(huán)依賴問題,看下一個(gè)問題:動(dòng)態(tài)代理
spring除了IOC,最津津樂道的功能就是AOP,所以再spring的設(shè)計(jì)中肯定需要考慮AOP
那我們模擬下AOP,先加一個(gè)注解

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopToString {
}

然后修改兩個(gè)bean, 再toString方法上都加上該注解

@AopToString
public String toString() {

然后beanFactory發(fā)現(xiàn)方法有@AopToString注解就是用cglib方法生成一個(gè)動(dòng)態(tài)代理(再toSring之前輸出"TO String AOP"),最終存入bean容器的是這個(gè)動(dòng)態(tài)代理對(duì)象而不是通過反射創(chuàng)建出的對(duì)象,一個(gè)AOP就實(shí)現(xiàn)了

但問題出現(xiàn)了,什么時(shí)候創(chuàng)建代理?
答:考慮到循環(huán)依賴,那么肯定是在添加二級(jí)緩存前,因?yàn)榇韺?duì)象和實(shí)例化出來的對(duì)象是兩個(gè)對(duì)象,假如A存在代理,B的依賴注入是A的原對(duì)象,那不是打錯(cuò)特錯(cuò)了嗎。所以一定是添加二級(jí)緩存前前創(chuàng)建代理,代碼實(shí)現(xiàn)一下,beanFactory修改

/**
 * 獲取bean
 */
@Override
public Object getBean(String name) throws BeansException {
    try {
        // 先去容器里拿
        Object singleton = getSingleton(name);
        // 如果沒有就創(chuàng)建
        if (singleton==null) {
            // 標(biāo)記正在創(chuàng)建
            beforeSingletonCreation(name);
            // 獲取bean定義
            MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
            // 實(shí)例化bean
            singleton = beanDefinition.getBeanClass().newInstance();
            //創(chuàng)建代理(新增)
            singleton = createBeanProxy(singleton, beanDefinition.getBeanClass());
            // 提前暴露加到二級(jí)緩存
            addEarly(name, singleton);
            // 填充屬性
            popular(singleton, beanDefinition.getBeanClass());
            // 注冊(cè)到容器
            registerSingleton(name, singleton);
            // 標(biāo)記創(chuàng)建完成
            afterSingletonCreation(name);
        }
        return singleton;
    } catch (InstantiationException e) {
        return null;
    } catch (IllegalAccessException e) {
        return null;
    }
}
private Object createBeanProxy(Object singleton, Class<?> clazz) {
    Method[] Methods = clazz.getMethods();
    // 循環(huán)所有方法
    for (Method field : Methods) {
        // 如果存在AopToString注解(簡化處理只代理一個(gè))
        if (field.isAnnotationPresent(AopToString.class)) {
            // 使用cglib創(chuàng)建代理
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
            enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                if (method.equals(field)) {
                    // 代理對(duì)象toSpring前輸出
                    System.out.print("TO String AOP ");
                }
                return methodProxy.invokeSuper(o, objects);
            });
            return enhancer.create();
        }
    }
    return singleton;
}

測試一下原測試方法

TO String AOP {"A":{"aName":"A","b":B}}
{"B":{"bName":"B","a":A}}

再循環(huán)依賴的前提下實(shí)現(xiàn)了動(dòng)態(tài)代理

三級(jí)緩存

網(wǎng)上都說三級(jí)緩存為了解決動(dòng)態(tài)代理,但其實(shí)到現(xiàn)在為止,只有二級(jí)緩存,動(dòng)態(tài)代理也解決了
那要三級(jí)緩存干嘛吶,沒有看見過官方的解釋,但是根據(jù)讀源碼猜測又這幾個(gè)考慮

  • spring的設(shè)計(jì)思路,動(dòng)態(tài)代理創(chuàng)建應(yīng)該是最后一步,應(yīng)該在所有事情(實(shí)例化,填充屬性,初始化)之后執(zhí)行
  • spring其實(shí)并不太希望出現(xiàn)循環(huán)依賴(新版的已經(jīng)默認(rèn)禁止循環(huán)依賴)
  • 為了不提倡的循環(huán)依賴而把動(dòng)態(tài)代理的創(chuàng)建時(shí)機(jī)提前,不值得

最終的實(shí)現(xiàn)方案:一般情況最后一步創(chuàng)建代理,如果出現(xiàn)循環(huán)依賴,提前創(chuàng)建代理
這個(gè)其實(shí)挺難實(shí)現(xiàn)的,因?yàn)樵谀硞€(gè)getBean執(zhí)行時(shí)候是沒有辦法確定是否存在循環(huán)依賴的,而且要在填充屬性前確定,這更難了。
spring的解決方案:
再加個(gè)三級(jí)緩存

  • 如果出現(xiàn)循環(huán)依賴
    getBean(A)時(shí),取消原來創(chuàng)建代理后存儲(chǔ)二級(jí)緩存的步驟,修改為存創(chuàng)建代理的方法至三級(jí)緩存,如果出現(xiàn)循環(huán)依賴getBean(B)的時(shí)候又反過來調(diào)用getBean(A),會(huì)去bean容器查找,此時(shí)二級(jí)緩存沒有,取三級(jí)緩存的方法并執(zhí)行生成帶有代理的對(duì)象,存入二級(jí)緩存并注入到B??梢哉=鉀Q循環(huán)依賴并提前創(chuàng)建
  • 如果沒有出現(xiàn)循環(huán)依賴
    getBean(A)時(shí),雖然也存入了三級(jí)緩存一個(gè)創(chuàng)建代理的方法,但是沒有循環(huán)依賴所以沒有再去bean容器查找,所以三級(jí)緩存相當(dāng)于白存了,正常填充屬性,再最后創(chuàng)建代理并返回即可

代碼修改下
先定義一個(gè)創(chuàng)建代理的方法的接口

@FunctionalInterface
public interface ObjectFactory<T> {

    T getObject() throws BeansException;

}

bean容器中加入三級(jí)緩存,完整代買如下(省略未實(shí)現(xiàn)方法)

public class MySingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    /** bean容器,完整的bean,一級(jí)緩存 **/
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    /** bean容器,不完整的bean,二級(jí)緩存 **/
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    /** bean創(chuàng)建方法容器,存儲(chǔ)不完整bean的創(chuàng)建方法,三級(jí)緩存 **/
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    /** 存儲(chǔ)正在創(chuàng)建的bean **/
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    /**
     * 查看bean是否正在創(chuàng)建
     */
    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }

    /**
     * 標(biāo)志bean正在創(chuàng)建
     */
    protected void beforeSingletonCreation(String beanName) {
        this.singletonsCurrentlyInCreation.add(beanName);
    }

    /**
     * 標(biāo)志bean創(chuàng)建完成
     */
    protected void afterSingletonCreation(String beanName) {
        this.singletonsCurrentlyInCreation.remove(beanName);
    }

    /**
     * 添加創(chuàng)建提前暴露bean的方法
     */
    protected void addSingletonFactory(String beanName, ObjectFactory<?> objectFactory) {
        this.singletonFactories.put(beanName, objectFactory);
    }

    /** 添加bean **/
    @Override
    public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        this.singletonObjects.put(beanName, singletonObject);
    }

    /** 獲取bean **/
    @Override
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    public Object getSingleton(String beanName, Boolean allowEarlyReference) {
        // 一級(jí)緩存拿
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果拿不到并且正在創(chuàng)建,去二級(jí)緩存拿
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            // 二級(jí)緩存娶不到,三級(jí)緩存創(chuàng)建再存入二級(jí)緩存
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    // 創(chuàng)建早器bean,包含代理的創(chuàng)建
                    singletonObject = singletonFactory.getObject();
                    // 這個(gè)還是不完整的bean存入二級(jí)緩存
                    this.earlySingletonObjects.put(beanName, singletonObject);
                }
            }
        }
        return singletonObject;
    }
public class MyBeanFactory extends MySingletonBeanRegistry implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {

    /** bean定義容器 **/
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

    /**
     * 注冊(cè)bean定義
     */
    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        beanDefinitionMap.put(beanName, beanDefinition);
    }

    /**
     * 獲取bean定義
     */
    @Override
    public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
        return this.beanDefinitionMap.get(beanName);
    }

    /**
     * 提前初始化所有bean
     * @throws BeansException
     */
    @Override
    public void preInstantiateSingletons() throws BeansException {
        // 循環(huán)所有bean定義
        for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
            // 生產(chǎn)bean
            getBean(entry.getKey());
        }
    }

    /**
     * 獲取bean
     */
    @Override
    public Object getBean(String name) throws BeansException {
        try {
            // 先去容器里拿
            Object singleton = getSingleton(name);
            // 如果沒有就創(chuàng)建
            if (singleton==null) {
                // 標(biāo)記正在創(chuàng)建
                beforeSingletonCreation(name);
                // 獲取bean定義
                MyBeanDefinition beanDefinition = (MyBeanDefinition) getBeanDefinition(name);
                // 獲取class
                Class<?> beanClass = beanDefinition.getBeanClass();
                // 實(shí)例化bean
                singleton = beanClass.newInstance();
                // 添加創(chuàng)建提前暴露bean的方法,包括代理
                Object finalSingleton = singleton;
                addSingletonFactory(name, ()-> createBeanProxy(finalSingleton, beanClass));
                // 填充屬性
                popular(singleton, beanClass);
                // 看看有沒有提前暴露
                Object singletonEarly = getSingleton(name, false);
                if (singletonEarly!=null) {
                    singleton = singletonEarly;
                } else {
                    // 創(chuàng)建代理
                    System.out.println(name + " create proxy at last");
                    singleton = createBeanProxy(finalSingleton, beanClass);
                }
                // 注冊(cè)到容器
                registerSingleton(name, singleton);
                // 標(biāo)記創(chuàng)建完成
                afterSingletonCreation(name);
            }
            return singleton;
        } catch (InstantiationException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
    }

    /**
     * 填充屬性
     * @param singleton
     * @param clazz
     */
    private void popular(Object singleton, Class<?> clazz) {
        // 循環(huán)屬性
        for (Field declaredField : clazz.getDeclaredFields()) {
            // 看看是否有MyAutowired注解
            MyAutowired annotation = declaredField.getAnnotation(MyAutowired.class);
            if (annotation!=null) {
                declaredField.setAccessible(true);
                try {
                    // 屬性賦值
                    declaredField.set(singleton, getBean(declaredField.getType().getSimpleName()));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 模仿cglib創(chuàng)建代理,這里做了特殊處理,這種代理方式
     * 實(shí)際上是給proxy對(duì)象增加一個(gè)target指向原對(duì)象,所以調(diào)用代理A的getB方法實(shí)際
     * 上是調(diào)用A.target.getB方法。這樣就解決了代理實(shí)際上沒有注入屬性的問題
     * @param singleton
     * @param clazz
     * @return
     */
    private Object createBeanProxy(Object singleton, Class<?> clazz) {
        Method[] Methods = clazz.getMethods();
        for (Method mth : Methods) {
            // 簡化處理只代理一個(gè)
            if (mth.isAnnotationPresent(AopToString.class)) {
                Enhancer enhancer = new Enhancer();
                enhancer.setSuperclass(clazz);
                enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                    if (method.equals(mth)) {
                        System.out.print("TO String AOP ");
                    }
                    return method.invoke(singleton, objects);
                });
                return enhancer.create();
            }
        }
        return singleton;
    }

再加個(gè)沒有循環(huán)依賴的BeanC

public class BeanC {
    public String cName = "C";

    @Override
    @AopToString
    public String toString() {
        return "{\"C\":{"
                + "\"cName\":\""
                + cName + '\"'
                + "}}";

    }
}

測試

public class CircularApplication {
    public static void main(String[] args) {
        System.out.println("===factory===");
        MyBeanFactory myBeanFactory = new MyBeanFactory();
        myBeanFactory.registerBeanDefinition("BeanA", new MyBeanDefinition(BeanA.class));
        myBeanFactory.registerBeanDefinition("BeanB", new MyBeanDefinition(BeanB.class));
        myBeanFactory.registerBeanDefinition("BeanC", new MyBeanDefinition(BeanC.class));
        myBeanFactory.preInstantiateSingletons();
        Object a = myBeanFactory.getBean("BeanA");
        Object b = myBeanFactory.getBean("BeanB");
        Object c = myBeanFactory.getBean("BeanC");
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}

輸出:

===factory===
BeanB create proxy at last
BeanC create proxy at last
TO String AOP {"A":{"aName":"A","b":B}}
{"BeanB":{"bName":"B","beanA":A}}
TO String AOP {"C":{"cName":"C"}}

可以看到,循環(huán)依賴沒問題,代理沒問題,而最后創(chuàng)建代理的只有BeanB和BeanC,BeanC就不用說了,沒有循環(huán)依賴,A和B互相依賴,由于先創(chuàng)建A再B,B創(chuàng)建時(shí)已經(jīng)可以獲取到A的二級(jí)緩存了,所以B并不需要提前暴露。

有點(diǎn)繞,有空補(bǔ)個(gè)時(shí)序圖吧
以上是BeanFactory的簡單模擬,起名基本參照spring,但spring的源碼肯定更復(fù)雜更多判斷,比如代理是通過后置處理器實(shí)現(xiàn)的,但大體思路差不多
over~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容