021.使用反射,編寫SpringIOC

什麼是SpringIOC

就是把每一個bean(實體類)與bean(實體類)之間的關係交給第三方容器進行管理。 而不是傳統的在你的對象內部直接控制。


SpringIOC實現原理

  • 讀取bean的XML配置文件
  • 使用beanId查找bean配置,並獲取配置文件中class地址
  • 使用java反射技術實例化對象
  • 獲取屬性配置,使用反射技術進行賦值

詳細步驟:

  • 1.利用傳入的參數獲取xml文件的流,並且利用dom4j解析成Document對象
  • 2.對於Document對象獲取根元素對象後對下面的標籤進行遍歷,判斷是否有符合的id.
  • 3.如果找到對應的id,相當於找到了一個Element元素,開始創建對象,先獲取class屬性,根據屬性值利用反射建立對象.
  • 4.遍歷標籤下的property標籤,並對屬性賦值.注意,需要單獨處理int,float類型的屬性.因爲在xml配置中這些屬性都是以字符串的形式來配置的,因此需要額外處理.
  • 5.如果屬性property標籤有ref屬性,說明某個屬性的值是一個對象,那麼根據id(ref屬性的值)去獲取ref對應的對象,再給屬性賦值.
  • 6.返回建立的對象,如果沒有對應的id,或者下沒有子標籤都會返回null

demo

maven

    <dependencies>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>

    </dependencies>

applicationContext.xml

<beans>
	<bean id="user1" class="cn.qbz.thread.day1120.User">
		<property name="name" value="xiaoMing"></property>
		<property name="age" value="6"></property>
	</bean>
	<bean id="user2" class="cn.qbz.thread.day1120.User">
		<property name="name" value="laoWang"></property>
		<property name="age" value="99"></property>
	</bean>
</beans>
package cn.qbz.thread.day1120;

public class User {
    private String name;
    private String age;

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}
package cn.qbz.thread.day1120;

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

import java.lang.reflect.Field;
import java.util.List;

public class ClassPathXmlApplicationContext {
    private String xpath;

    public ClassPathXmlApplicationContext(String xpath) {
        this.xpath = xpath;
    }

    public Object getBean(String beanId) throws Exception {
        if (isEmpty(beanId)) {
            throw new Exception("bean Id is null !");
        }

        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(this.getClass().getClassLoader().getResource(xpath));

        //獲取到根節點
        Element rootElement = document.getRootElement();
        //獲取到根節點下的所有的子節點
        List<Element> elements = rootElement.elements();

        for (Element element : elements) {
            //獲取到節點上的屬性
            String id = element.attributeValue("id");
            if (isEmpty(id)) {
                continue;
            }
            if (!id.equals(beanId)) {
                continue;
            }
            // 使用java反射機制初始化對象
            String beanClass = element.attributeValue("class");
            Class<?> forName = Class.forName(beanClass);
            Object newInstance = forName.newInstance();
            List<Element> propertyElementList = element.elements();
            for (Element el : propertyElementList) {
                String name = el.attributeValue("name");
                String value = el.attributeValue("value");
                Field declaredField = forName.getDeclaredField(name);
                declaredField.setAccessible(true);
                declaredField.set(newInstance, value);
            }
            return newInstance;
        }
        return null;
    }

    public Boolean isEmpty(String str) {
        return (str == null || "".equals(str.trim()));
    }
}
package cn.qbz.thread.day1120;

public class SpringIOCTest {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext classPath = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = (User) classPath.getBean("user2");
        System.out.println(user.getName() + "---" + user.getAge());
    }
}

注意: this.getClass().getClassLoader().getResourceAsStream(xmlPath) 獲取當前項目路徑xmlPath

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章