Spring入門 及 模擬springioc

簡介

spring:是一個大型的容器,用來管理協調各層之間的調用。

1. 核心:

  • IOC/DI:控制反轉/依賴注入 Inversion of Control/Dependency Injection.
  • AOP:Asepct Oriented Programming.

2. spring特點:

  • 輕量級:不是因爲其代碼量少,而是spring是非侵入式的。及基於spring開發的應用,不需要依賴spring api,即在使用spring時,無需實現或繼承spring的任何接口或父類。
  • 容器:因爲spring包含並管理應用對象的生命週期。
  • 一站式框架:在IOC和AOP基礎上,可以整合各種企業應用的開源框架。

創建第一個Spring項目

這裏參考官方文檔:https://spring.io/
這裏使用maven進行構建。

1. 導入相關依賴

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.12</version>
	<scope>test</scope>
</dependency>
	
<!-- spring的依賴包 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-beans</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>5.2.3.RELEASE</version>
</dependency>

2. 創建實體類

private int deptno;
private String dname;

public int getDeptno() {
	return deptno;
}
public void setDeptno(int deptno) {
	this.deptno = deptno;
}
public String getDname() {
	return dname;
}
public void setDname(String dname) {
	this.dname = dname;
}

3. 創建spring的xml配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- 需要spring ioc容器管理的類 -->
	<bean id="dept" class="com.hx.spring.Dept"> 
		<!--id:根據id注值 class:根據類路徑注入 -->
		<property name="deptno" value="101"></property>
		<property name="dname" value="技術部"></property>
	</bean>
</beans>

4. 創建測試類

@Test
public void test1(){
	//實例化ioc容器
	ApplicationContext context = new 	ClassPathXmlApplicationContext("spring-beans.xml");
	//從容器中獲取所需要的對象
	Dept dept = (Dept) context.getBean("dept");		//括號中填寫xml中配置的實體類的id
	System.out.println(dept);
}

模擬springioc

1. 創建ClassDefinition類

/**
 * 類定義,用來解析每個類的信息
 * @author Huathy
 * @date 2020年3月4日
 */
public class ClassDefinition {
	private String id;				//唯一標識
	private String className;		//類的全路徑	
	private Map<String,String> pros;
	
	public ClassDefinition(String id, String className) {
		super();
		this.id = id;
		this.className = className;
		pros = new HashMap<String,String>();
	}
	public void addPro(String key, String value) {
		pros.put(key, value);
	}
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public Map<String, String> getPros() {
		return pros;
	}
	public void setPros(Map<String, String> pros) {
		this.pros = pros;
	}
}

2. 創建 ApplicationContext 接口

/**
 * 
 * @author Huathy
 * @date 2020年3月4日
 */
public interface ApplicationContext {
	public Object getBean(String id);
}

3. 創建 ClassPathXmlApplicationContext 類

/**
 * 
 * @author Huathy
 * @date 2020年3月4日
 */
public class ClassPathXmlApplicationContext implements ApplicationContext {
	private Map<String,Object> singeton = new HashMap<String,Object>();
	private List<ClassDefinition> beans = new ArrayList<>();
	
	public ClassPathXmlApplicationContext(String path) {
		parseXml(path);
		try {
			makeInstance();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	private void makeInstance() throws Exception {
		if(beans.isEmpty()){
			return;
		}
		Class c = null;
		Method[] methods = null;
		Map<String,Method> map = null;
		String methodName = null;
		Object obj = null;
		Map<String,String> properties = null;
		Method md = null;
		String typeName = null;
		
		for(ClassDefinition cls : beans){
			c = Class.forName( cls.getClassName() );
			obj = c.newInstance();
			properties = cls.getPros();
			if(properties == null || properties.isEmpty()){
				singeton.put(cls.getId(), obj);
				continue;
			}
			methods = c.getDeclaredMethods();
			map = new HashMap<String,Method>();
			for(Entry<String, String> entry : properties.entrySet()){
				methodName = entry.getKey();
				methodName = "set" + methodName.substring(0,1).toUpperCase() + methodName.substring(1);
				
				md = map.get(methodName);
				if(md == null){
					continue;
				}
				
				typeName = md.getParameterTypes()[0].getSimpleName();
				if( "int".equals(typeName) || "Integer".equals(typeName) ){
					md.invoke(obj, Integer.parseInt(entry.getValue()));
				}else if( "float".equals(typeName) || "Float".equals(typeName) ){
					md.invoke(obj, Float.parseFloat(entry.getValue()));
				}else if( "double".equals(typeName) || "Double".equals(typeName) ){
					md.invoke(obj, Double.parseDouble(entry.getValue()));
				}else{
					md.invoke(obj, entry.getValue());
				}
			}
			singeton.put(cls.getId(), obj);
		}
	}

	/**
	 * 解析xml文件
	 * @param path
	 */
	private void parseXml(String path){
		SAXReader read = new SAXReader();
		Document doc = null;
		try(InputStream is = this.getClass().getClassLoader().getResourceAsStream(path)){
			doc = read.read(is);
			XPath xpath = doc.createXPath("//hx:bean");		//查找hx下的bean
			
			//這裏需要對命名空間進行處理
			Map<String,String> nsmap = new HashMap<>();
			nsmap.put("hx", "http://www.springframework.org/schema/beans");	//使用hx來替代後面的
			xpath.setNamespaceURIs(nsmap);	//設置命名空間信息
			
			List<Element> nodes = xpath.selectNodes(doc);
			
			if(nodes.isEmpty()){
				return;		//判斷xml中是否配置,如果沒有配置,直接返回
			}
			
			String id = null;
			String className = null;
			ClassDefinition bean = null;
			List<Element> properties = null;
			for(Element el : nodes){
				id = el.attributeValue("id");
				className = el.attributeValue("class");
				bean = new ClassDefinition(id, className);
				
				properties = el.elements();		//取出這個bean對象的屬性值
				if(properties != null && !properties.isEmpty()){
					for(Element pro : properties){	//循環所有屬性值
						bean.addPro(pro.attributeValue("name"),pro.attributeValue("value"));
					}
				}
				beans.add(bean);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public Object getBean(String id) {
		return singeton.getOrDefault(id, null);
	}
}

4. 創建實體類、xml配置文件、測試類

  1. 實體類
public class Dept implements Serializable{
	private int deptno;
	private String dname;
	private List<Emp> emps;
	public List<Emp> getEmps() {
		return emps;
	}
	public void setEmps(List<Emp> emps) {
		this.emps = emps;
	}
	public int getDeptno() {
		return deptno;
	}
	public void setDeptno(int deptno) {
		this.deptno = deptno;
	}
	public String getDname() {
		return dname;
	}
	public void setDname(String dname) {
		this.dname = dname;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + deptno;
		result = prime * result + ((dname == null) ? 0 : dname.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Dept other = (Dept) obj;
		if (deptno != other.deptno)
			return false;
		if (dname == null) {
			if (other.dname != null)
				return false;
		} else if (!dname.equals(other.dname))
			return false;
		return true;
	}
	@Override
	public String toString() {
		return "Dept [deptno=" + deptno + ", dname=" + dname + "]";
	}
	public Dept(int deptno, String dname) {
		super();
		this.deptno = deptno;
		this.dname = dname;
	}
	public Dept() {
		super();
	}
}
  1. xml配置文件spring-beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- 需要spring ioc容器管理的類 -->
	<bean id="dept" class="com.hx.spring.entity.Dept">
		<!-- class:根據類路徑注入 -->
		<property name="deptno" value="101"></property>
		<property name="dname" value="技術部"></property>
	</bean>
</beans>
  1. 測試類
public class AppTest {
	@Test
	public void test1(){
		//實例化ioc容器
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");	
		//從容器中獲取所需要的對象
		Dept dept = (Dept) context.getBean("dept");		//括號中填寫xml中配置的實體類id
		System.out.println(dept);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章