天天看點

我的學習之路-Spring Ioc

加深spring架構了解,實作簡單的Ioc容器

最近學習到了SSM架構,記錄一下spring的Ioc容器學習。

什麼是Ioc?

Ioc 英文就是 Inversion Of Control,意思是控制反轉。

IoC 是指在程式開發中,執行個體的建立不再由調用者管理,而是由 Spring 容器建立。Spring 容器會負責控制程式之間的關系,而不是由程式代碼直接控制,是以,控制權由程式代碼轉移到了 Spring 容器中,控制權發生了反轉,這就是 Spring 的 IoC 思想。

簡單一點說,就是以前我們建立對象的時候,要自己敲,new 一個新對象,現在把建立對象的任務交給spring容器處理,由spring容器建立對象,我們直接使用就好。

思想簡單了解

我們将需要建立的對象和依賴關系通過bean标簽的形式寫入配置檔案(applicationContext.xml),架構讀取配置檔案,建立對象并處理依賴關系。

寫一個簡單的Ioc容器

建立實體對象類,将類資訊寫入applicationContext.xml檔案,初始化容器,讀取配置檔案,獲得類資訊,資料資訊,利用反射機制獲得類對象,建立類,将資料注入類。

實作

1.建立項目

項目名 easyIoc,結構如下

我的學習之路-Spring Ioc

2.實體類:Apple

package com.Ioc.entity;

public class Apple {
    private String name;
    private String color;
    private String taste;

    @Override
    public String toString() {
        return "Apple{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                ", taste='" + taste + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getTaste() {
        return taste;
    }

    public void setTaste(String taste) {
        this.taste = taste;
    }
}

           

3.配置檔案:applicationContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean id="redApple" class="com.Ioc.entity.Apple">
        <property name="name" value="紅蘋果"/>
        <property name="color" value="紅色"/>
        <property name="taste" value="甜"/>
    </bean>
</beans>
           

4.接口類:applicationContext

package com.Ioc.context;

public interface ApplicationContext {
    public Object getBean(String beanId);
}
           

5.實作類:ClassPathXmlApplicationContext

package com.Ioc.context;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ClassPathXmlApplicationContext implements ApplicationContext {
    private Map IocContainer = new HashMap();

    public ClassPathXmlApplicationContext() {
        try {
//            讀取xml配置檔案
//            getResource用于從classpath擷取指定檔案資源 getPath擷取路徑
            String filePath = this.getClass().getResource("/applicationContext.xml").getPath();
//            URL解碼,防止出現中文路徑丢失問題
            filePath = new URLDecoder().decode(filePath, "UTF-8");
//            加載解析xml檔案,獲得Document對象
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File(filePath));
//            擷取根節點集合
            List<Node> beans = document.getRootElement().selectNodes("bean");
            for (Node node : beans) {
//                強制轉換成Element對象
                Element element = (Element) node;
//                提取屬性
                String id = element.attributeValue("id");
                String className = element.attributeValue("class");
//                利用java反射擷取類對象
                Class c = Class.forName(className);
//                接收類對象
                Object obj = c.newInstance();
//                獲得屬性節點
                List<Node> propertys = element.selectNodes("property");
                for (Node property : propertys) {
                    Element ele = (Element) property;
//                    獲得屬性名和屬性值
                    String name = ele.attributeValue("name");
                    String value = ele.attributeValue("value");
//                    動态注入
//                    定義方法名,set後第一個字元大寫
                    String setMethodName = "set" + name.substring(0,1).toUpperCase()+name.substring(1);
                    System.out.println("準備執行" + setMethodName + "方法注入資料");
//                    利用反射,通過方法名調用方法
//                    getMethod(),第一個參數:方法名,第二個參數:方法的參數的類型
                    Method setMethod = c.getMethod(setMethodName, String.class);
//                    調用方法
                    setMethod.invoke(obj, value);//通過setter方法注入資料
                }
//                放入容器
                IocContainer.put(id, obj);
            }
            System.out.println(IocContainer);
            System.out.println("初始化完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public Object getBean(String beanId) {
        return IocContainer.get(beanId);
    }
}
           

6.導入依賴:dom4j和jaxen (pom.xml)

<dependencies>
        <!--dom4j: java的xml解析元件,底層依賴jaxen-->
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <!--jaxen:Xpath表達式解釋器-->
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
        </dependency>
    </dependencies>
           

7.程式入口:Application

package com.Ioc;

import com.Ioc.context.ApplicationContext;
import com.Ioc.context.ClassPathXmlApplicationContext;
import com.Ioc.entity.Apple;

public class Application {
    public static void main(String[] args) {
//        初始化容器
        ApplicationContext context = new ClassPathXmlApplicationContext();
        System.out.println((Apple)context.getBean("redApple"));
    }
}
           

8.結果

我的學習之路-Spring Ioc

結語

有問題希望大家指出。學無止境,歡迎交流。