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);
	}
}
发布了40 篇原创文章 · 获赞 16 · 访问量 8631

猜你喜欢

转载自blog.csdn.net/qq_40366738/article/details/104597944