看完這篇本身均可以寫Spring IOC 容器 Bean 對象實例化--樂字節java

Spring IOC 容器 Bean 對象實例化模擬

思路:java

  1. 定義Bean 工廠接口,提供獲取bean方法
  2. 定義Bean工廠接口實現類,解析配置文件,實例化Bean對象
  3. 實現獲取Bean方法

定義 Bean 屬性對象

package com.xxxx.spring;

/**
 * bean對象
 *      用來接收配置文件中bean標籤的id與class屬性值
 */
public class MyBean {

    private String id; // bean對象的id屬性值
    private String clazz; // bean對象的類路徑

    public MyBean() {
    }

    public MyBean(String id, String clazz) {
        this.id = id;
        this.clazz = clazz;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

若有疑問,可加入羣:10803-55292,輸入暗號13,便可有大佬幫助spring

添加 dom4j 座標依賴

<!-- dom4j -->
<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
</dependency>
<!-- XPath -->
<dependency>
    <groupId>jaxen</groupId>
    <artifactId>jaxen</artifactId>
    <version>1.1.6</version>
</dependency>

準備自定義配置文件

spring.xmldom

<?xml version="1.0" encoding="utf-8" ?>
<beans>
    <bean id="userService" class="com.xxxx.service.UserService"></bean>
    <bean id="accountService" class="com.xxxx.service.AccountService"></bean>
</beans>

定義 Bean 工廠接口

package com.xxxx.spring;

/**
 * Bean 工廠接口定義
 */
public interface MyFactory {
    // 經過id值獲取對象
    public Object getBean(String id);
}

定義 Bean 接口的實現類

package com.xxxx.spring;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 模擬Spring的實現
 *  一、經過構造器獲得相關配置文件
 *  二、經過dom4j解析xml文件,獲得List   存放id和class
 *  三、經過反射實例化獲得對象   Class.forName(類的全路徑).newInstance(); 經過Map<id,Class>存儲
 *  四、獲得指定的實例化對象
 */
public class MyClassPathXmlApplicationContext implements BeanFactory {

    private Map beans = new HashMap(); // 實例化後的對象放入map
    private List<MyBean> myBeans; // 存放已讀取bean 配置信息

    /* 一、經過構造器獲得相關配置文件 */
    public MyClassPathXmlApplicationContext(String fileName) {

        /* 二、經過dom4j解析xml文件,獲得List (存放id和class) */
        this.parseXml(fileName);

        /* 三、經過反射實例化獲得對象Class.forName(類路徑).newInstance();  經過Map存儲 */
        this.instanceBean();

    }

    /**
     * 經過dom4j解析xml文件,獲得List   存放id和class
     *  一、獲取解析器
     *  二、獲得配置文件的URL
     *  三、經過解析器解析xml文件(spring.xml)
     *  四、經過xpath語法,獲取beans標籤下的全部bean標籤
     *  五、經過指定語法解析文檔對象,返回集合
     *  六、判斷集合是否爲空,遍歷集合
     *  七、獲取標籤元素中的屬性
     *  八、獲得Bean對象,將Bean對象設置到集合中
     * @param fileName
     */
    private void parseXml(String fileName) {
        // 一、獲取解析器
        SAXReader reader = new SAXReader();
        // 二、獲得配置文件的URL
        URL url = this.getClass().getClassLoader().getResource(fileName);
        try {
            // 三、經過解析器解析xml文件(spring.xml)
            Document document = reader.read(url);
            // 四、經過xpath語法,獲取beans標籤下的全部bean標籤
            XPath xPath = document.createXPath("beans/bean");
            // 經過指定語法解析文檔對象,返回集合
            List<Element> list = xPath.selectNodes(document);
            // 判斷集合是否爲空,遍歷集合
            if (list != null && list.size() > 0) {
                myBeans = new ArrayList<>();
                for(Element el : list) {
                    // 獲取標籤元素中的屬性
                    String id = el.attributeValue("id"); // id 屬性值
                    String clazz = el.attributeValue("class"); // class 屬性值
                    System.out.println(el.attributeValue("id"));
                    System.out.println(el.attributeValue("class"));
                    // 獲得Bean對象
                    MyBean bean = new MyBean(id, clazz);
                    // 將Bean對象設置到集合中
                    myBeans.add(bean);
                }
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 經過反射實例化獲得對象  
     *  Class.forName(類的全路徑).newInstance();  
     *  經過Map<id,Class>存儲
     */
    private void instanceBean() {
        // 判斷bean集合是否爲空,不爲空遍歷獲得對應Bean對象
        if (myBeans != null && myBeans.size() > 0) {
            for (MyBean bean : myBeans){                                      
                try {
                    // 經過類的全路徑實例化對象
                    Object object = Class.forName(bean.getClazz()).newInstance();
                    // 將id與實例化對象設置到map對象中
                    beans.put(bean.getId(), object);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 經過key獲取map中的指定value
     * @param id
     * @return
     */
    @Override
    public Object getBean(String id) {
        Object object = beans.get(id);
        return object;
    }
}

測試自定義 IOC 容器

  1. 建立與配置文件中對應的Bean對象ide

    UserService.java測試

    package com.xxxx.service;
    
    public class UserService {
    
       public void test(){
           System.out.println("UserService Test...");
       }
    }

    AccountService.javathis

    package com.xxxx.service;
    
    public class AccountService {
    
       public void test(){
           System.out.println("AccountService Test...");
       }
    }
  2. 測試是否能夠獲取實例化的Bean對象url

    package com.xxxx;
    
    import com.xxxx.spring.MyFactory;
    import com.xxxx.spring.MyClassPathXmlApplicationContext;
    import com.xxxx.service.AccountService;
    import com.xxxx.service.UserService;
    
    public class App {
    
       public static void main(String[] args) {
           MyFactory factory = new MyClassPathXmlApplicationContext("spring.xml");
           // 獲得實例化對象
           UserService userService = (UserService) factory.getBean("userService");
           userService.test();
    
           UserService userService2 = (UserService) factory.getBean("userService");
           System.out.println(userService+"=====" + userService2);
    
           AccountService accountService = 
           (AccountService)factory.getBean("accountService");
           accountService.test();
    
       }
    }

    ​ Spring 容器在啓動的時候 讀取xml配置信息,並對配置的 bean 進行實例化(這裏模擬的比較簡單,僅用於幫助你們理解),同時經過上下文對象提供的 getBean() 方法拿到咱們配置的 bean 對象,從而實現外部容器自動化維護並建立 bean 的效果。.net

image

相關文章
相關標籤/搜索