天天看點

Spring_IOC底層實作模拟

在學習spring一開始,書上就會提及spring中ioc(控制反轉)和aop(面向切面)是兩個重點内容。

那麼究竟什麼是ioc呢,下面就簡單總結一下ioc:(ps:關于spring的aop及其他知識将下後續文章總結)

IoC不是一種技術,隻是一種思想,一個重要的面向對象程式設計的法則,它能指導我們如何設計出松耦合、更優良的程式。傳統應用程式都是由我們在類内部主動建立依賴對象,進而導緻類與類之間高耦合,難于測試;有了IoC容器後,把建立和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,是以對象與對象之間是松散耦合,這樣也友善測試,利于功能複用,更重要的是使得程式的整個體系結構變得非常靈活。

其實IoC對程式設計帶來的最大改變不是從代碼上,而是從思想上,發生了“主從換位”的變化。應用程式原本是老大,要擷取什麼資源都是主動出擊,但是在IoC/DI思想中,應用程式就變成被動的了,被動的等待IoC容器來建立并注入它所需要的資源了。

IoC很好的展現了面向對象設計法則之一—— 好萊塢法則:“别找我們,我們找你”;即由IoC容器幫對象找相應的依賴對象并注入,而不是由對象主動去找。

IoC和DI由什麼關系呢?其實它們是同一個概念的不同角度描述,由于控制反轉概念比較含糊(可能隻是了解為容器控制對象這一個層面,很難讓人想到誰來維護對象關系),是以2004年大師級人物Martin Fowler又給出了一個新的名字:“依賴注入”,相對IoC 而言,“依賴注入”明确描述了“被注入對象依賴IoC容器配置依賴對象”。IOC的了解

那麼接下來就開始我們的模拟:

Spring_IOC底層實作模拟

User.java:

package h.l.ioc;

public class User {// 使用者類

	private String username;// 賬号
	private String password;// 密碼
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public User(String username, String password) {
		super();
		this.username = username;
		this.password = password;
	}
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + "]";
	}

}
           

IOC.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
	<bean id="user2" class="club.j208.demo.User2"></bean>
	<bean id="user" class="h.l.ioc.User"></bean>
</beans>
           

IOCByself.java:

/**   
* @Title: IOCByself.java 
* @Package h.l.ioc 
* @Description: 模拟spring中IOC底層實作
* @author HL
* @version V1.0   
*/
package h.l.ioc;

import java.io.File;
import java.util.Iterator;

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

/************************************************************************
 * 1、使用dom4j解析xml配置檔案 2、擷取配置檔案中指定bean的class屬性 3、得到屬性值使用反射建立對象 *
 ***********************************************************************/
public class IOCByself {

	// 解析XML檔案
	public Document parseXML(File file) {
		SAXReader saxReader = new SAXReader();
		Document document = null;
		try {
			document = saxReader.read(file);
		} catch (DocumentException e) {
			System.out.println(e.getMessage());
		}
		return document;
	}

	/**
	 * bean的格式<bean id="" class=""/>
	 * 
	 * @param beanId傳入bean的id
	 * @return 建立bean的id對應的類的對象
	 */
	public Object getService(String beanId) {
		Document document = parseXML(new File("src/h/l/ioc/IOC.xml"));
		Element root = document.getRootElement();
		String className="";
		for (Iterator<Element> it = root.elementIterator(); it.hasNext();) {
			Element element = it.next();
			if(element.valueOf("@id").equals(beanId)) {
				className=element.valueOf("@class");
			}
		}
		Object object=null;
		try {
			Class<?> clazz=Class.forName(className);
			object=clazz.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return object;
	}
}
           

 IOCByselfTest.java:

/**   
* @Title: IOCByselfTest.java 
* @Package h.l.ioc 
* @Description: 測試
* @author HL
* @version V1.0   
*/
package h.l.ioc;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class IOCByselfTest {

	IOCByself iocByself = null;
	@BeforeEach
	void setUp() throws Exception {
		iocByself = new IOCByself();
	}

	@Test
	void test() {
		User user = (User) iocByself.getService("user");
		user.setUsername("Is-Me-HL");
		user.setPassword("root");
		System.out.println(user);
	}

}
           

OK,Just do it!

注:以上文章僅是個人學習過程總結,若有不當之處,望不吝賜教。

繼續閱讀