Spring是一個分層的JavaSE/EE full-stack(一站式) 輕量級開源框架。也是幾乎全部Java工做者必需要掌握的框架之一,其優秀的設計思想以及其代碼實現上的藝術也是咱們須要掌握的。要學習Spring,除了在咱們的項目中使用以外,也須要對它的源碼進行研讀,可是Spring的實現涵蓋的知識不少,在加上其中的類的數量也是很是的多,在咱們閱讀源碼時可能會在幾十個類之間穿插閱讀,頗有可能一不當心就致使思惟混亂。有鑑於此,我這裏先對Spring中的幾個重要的模塊進行一個手動的簡易實現,一是熟悉這些模塊的原理,同時也是仿造Spring中的結構來對後面閱讀源碼打下基礎。html
Inversion of Control即控制反轉,其意思是將咱們以前由客戶端代碼來建立的對象交由IOC容器來進行控制,對象的建立,初始化以及後面的管理都由IOC完成。設計模式
工廠模式。IOC容器來負責建立管理類實例對象,在須要時向IOC進行申請,從IOC中獲取。因此IOC容器也稱爲bean工廠。bash
工廠模式是一種比較簡單易懂的設計模式,這裏就不在介紹了,若是有須要的能夠看看這個:工廠模式。併發
IOC的主要的功能即是對Bean進行管理,包括建立、初始化、管理以及銷魂的工做。首先咱們面對的問題就是咱們怎麼讓IOC可以建立一個Bean?爲了建立Bean咱們須要提供一些什麼?框架
在不手動經過new關鍵字建立的狀況下建立類實例的對象方法有兩種:ide
clazz.getClass().newInstance();
。public class PersonFactory{
public Person getPerson(){
return new Person();
}
}
複製代碼
經過分析上面的兩種方法能夠輕鬆得出答案。post
對於反射的方式咱們僅需提供實例的Class對象。學習
對於工廠方法咱們須要提供的就是建立該類的工廠名(factoryName)和方法名(methodName);測試
IOC容器是對bean的整個生命週期進行管理,除了建立以外還須要對bean進行初始化,以及不須要時對bean進行銷燬的工做(如釋放資源等)。因此咱們還須要提供初始化和銷燬等操做。ui
到這裏建立bean須要的基本分析完了,看類圖:
Bean的定義解決了,可是這個bean定義以及建立好的Bean實例放在哪裏呢,咱們須要一個統一的地方來存放這些東西以方便咱們要用的時候方便取。
咱們定義一個Bean工廠來存放bean,在須要的時候懂bean工廠中取便可,bean工廠對外提供的也僅僅是一個獲取bean的方法便可,因爲bean的類型不定,因此返回值定位Object。
到了如今咱們有了建立bean的Bean定義,有了存放和管理bean的Bean工廠,如今須要考慮的事怎麼來聯繫這兩個類,咱們還須要另一個接口,接口的功能是讓咱們能註冊和獲取bean定義,這裏咱們經過beanName來區分不一樣的bean。
到這裏咱們實現一個簡易的IOC容器的須要的東西基本準備完成了,看下基本類圖:
基本代碼實現:
DefaultBeanDefinition:
public class DefaultBeanDefinition implements BeanDefinition{
private Class<?> clazz;
private String beanFactoryName;
private String createBeanMethodName;
private String staticCreateBeanMethodName;
private String beanInitMethodName;
private String beanDestoryMethodName;
private boolean isSingleton;
// setter
public void setSingleton(boolean singleton) {
isSingleton = singleton;
}
@Override
public Class<?> getBeanClass() {
return this.clazz;
}
@Override
public String getBeanFactory() {
return this.beanFactoryName;
}
@Override
public String getCreateBeanMethod() {
return this.createBeanMethodName;
}
@Override
public String getStaticCreateBeanMethod() {
return this.staticCreateBeanMethodName;
}
@Override
public String getBeanInitMethodName() {
return this.beanInitMethodName;
}
@Override
public String getBeanDestoryMethodName() {
return this.beanDestoryMethodName;
}
@Override
public String getScope() {
return this.isSingleton?BeanDefinition.SINGLETION :BeanDefinition.PROTOTYPE;
}
@Override
public boolean isSingleton() {
return this.isSingleton;
}
@Override
public boolean isPrototype() {
return !this.isSingleton;
}
}
複製代碼
DefaultBeanFactory:
public class DefaultBeanFactory implements BeanFactory, BeanDefinitionRegistry, Closeable {
private Log log = LogFactory.getLog(this.getClass());
//ConcurrentHashMap應對併發環境
private Map<String, BeanDefinition> bdMap = new ConcurrentHashMap<>();
private Map<String, Object> beanMap = new ConcurrentHashMap<>();
@Override
public void register(BeanDefinition bd, String beanName) {
Assert.assertNotNull("beanName不能爲空 beanName", beanName);
Assert.assertNotNull("BeanDefinition不能爲空", bd);
if(bdMap.containsKey(beanName)){
log.info("[" + beanName + "]已經存在");
}
if(!bd.validate()){
log.info("BeanDefinition不合法");
}
if(!bdMap.containsKey(beanName)){
bdMap.put(beanName, bd);
}
}
@Override
public boolean containsBeanDefinition(String beanName) {
return bdMap.containsKey(beanName);
}
@Override
public BeanDefinition getBeanDefinition(String beanName) {
if(!bdMap.containsKey(beanName)){
log.info("[" + beanName + "]不存在");
}
return bdMap.get(beanName);
}
public Object doGetBean(String beanName) throws InstantiationException, IllegalAccessException {
if(!beanMap.containsKey(beanName)){
log.info("[" + beanName + "]不存在");
}
Object instance = beanMap.get(beanName);
if(instance != null){
return instance;
}
//不存在則進行建立
if(!this.bdMap.containsKey(beanName)){
log.info("不存在名爲:[" + beanName + "]的bean定義");
}
BeanDefinition bd = this.bdMap.get(beanName);
Class<?> beanClass = bd.getBeanClass();
if(beanClass != null){
instance = createBeanByConstruct(beanClass);
if(instance == null){
instance = createBeanByStaticFactoryMethod(bd);
}
}else if(instance == null && StringUtils.isNotBlank(bd.getStaticCreateBeanMethod())){
instance = createBeanByFactoryMethod(bd);
}
this.doInit(bd, instance);
if(instance != null && bd.isSingleton()){
beanMap.put(beanName, instance);
}
return instance;
}
private void doInit(BeanDefinition bd, Object instance) {
Class<?> beanClass = instance.getClass();
if(StringUtils.isNotBlank(bd.getBeanInitMethodName())){
try {
Method method = beanClass.getMethod(bd.getBeanInitMethodName(), null);
method.invoke(instance, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 構造方法建立實例
* @param beanClass
* @return
*/
private Object createBeanByConstruct(Class<?> beanClass) {
Object instance = null;
try {
instance = beanClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
/**
* 普通工廠方法建立實例
* @param bd
* @return
*/
private Object createBeanByFactoryMethod(BeanDefinition bd) {
Object instance = null;
try {
//獲取工廠類
Object factory = doGetBean(bd.getBeanFactory());
//獲取建立實例的方法
Method method = factory.getClass().getMethod(bd.getCreateBeanMethod());
//執行方法
instance = method.invoke(factory, null);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
/**
* 靜態方法建立實例
* @param bd
* @return
*/
private Object createBeanByStaticFactoryMethod(BeanDefinition bd) {
Object instance = null;
try {
Class<?> beanClass = bd.getBeanClass();
//獲取建立實例的方法
Method method = beanClass.getMethod(bd.getStaticCreateBeanMethod());
instance = method.invoke(beanClass, null);
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
@Override
public Object getBean(String beanName) {
if(!beanMap.containsKey(beanName)){
log.info("[" + beanName + "]不存在");
}
return beanMap.get(beanName);
}
@Override
public void close() throws IOException {
Set<Map.Entry<String, BeanDefinition>> entries = bdMap.entrySet();
for(Map.Entry<String, BeanDefinition> entry: entries){
BeanDefinition value = entry.getValue();
String destoryMethodName = value.getBeanDestoryMethodName();
try {
Method method = value.getBeanClass().getMethod(destoryMethodName, null);
method.invoke(value.getBeanClass(), null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
複製代碼
簡單測試一下: 實例bean:
public class User {
private String name;
private int age;
//getter setter
public void init(){
System.out.println("init...");
}
public void destory(){
System.out.println("destory...");
}
}
複製代碼
工廠類:
public class TestFactory {
public Object createMethod(){
return new User();
}
public static Object staticCreateMethod(){
return new User();
}
}
複製代碼
測試類:
public class MySpringTest {
static DefaultBeanFactory factory = new DefaultBeanFactory();
@Test
public void test() throws IllegalAccessException, InstantiationException {
DefaultBeanDefinition bd = new DefaultBeanDefinition();
bd.setClazz(User.class);
bd.setSingleton(true);
bd.setBeanFactoryName("TestFactory");
bd.setCreateBeanMethodName("createMethod");
bd.setStaticCreateBeanMethodName("staticCreateMethod");
bd.setBeanInitMethodName("init");
factory.register(bd, "user");
System.out.println(factory.doGetBean("user"));
}
}
複製代碼
一個簡易的容器就這樣實現了,固然咱們這裏只是具有了基本的功能,實際上還差的遠,好比帶參數的bean的實例化等功能。可是IOC的基本原理已經表達出來了,後面咱們只需在這個基礎上添加新的功能便可。