概述
看了好久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è)接口ConfigurableListableBeanFactory和BeanDefinitionRegistry,下面分別整理下這兩個(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)的接口

看名字就知道這是一個(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處理的

實(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~