Spring学习-手写IOC(xml版)

1.IOC介绍

ioc:依赖注入(本人比较喜欢这类描述),字面意思比较好理解,我们在class类中定义的一些对象属性,默认值为null,spring框架自动帮我们注入这些属性的实例对象。不需要再用传统的方式每次使用对象时,在代码中new这个对象,spring默认创建对象的方式是单例(在多线程并发时要注意)。

2.如何实现

问题:定义属性(javaBean对象)时,怎么自动给属性(这个javaBean)赋值

原理:第一步,利用java的反射技术,通过javabean的类路径全名反射生成javabean实例对象;第二步,使用反射通过field中的set方法设置该属性的值为生成的实例对象即可(xml版本中未实现,采用getBean方法)。

3.在xml配置文件中获取类全名

user-annotation.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" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
	<bean id="userService" class="com.huajie.day1.impl.UserServiceImpl">
	</bean>

</beans>

4.使用dom4j,操作xml,获取节点beans中的bean,更加bean的id属性定为到唯一的bean对象,再获取class属性为类路径全名

部分关键代码如下:

// 解析xml文件
	public List<Element> readerXML() throws DocumentException {

		SAXReader saxReader = new SAXReader();
		Document read = saxReader.read(getClassPath(xmlPath));
		// 获取根节点
		Element rootElement = read.getRootElement();
		List<Element> listnodes = rootElement.elements();
		return listnodes;

	}
private String getBeanClassNameById(List<Element> liste, String beanId){
		// 遍历节点获取bean
		for (Element element : liste) {
			String xmlBeanId = element.attributeValue("id");
			if (StringUtils.isEmpty(xmlBeanId)) {
				continue;
			}
			if (beanId.equals(xmlBeanId)) {
				String className = element.attributeValue("class");
				return className;
			}
		}
		return null;
	}

5.使用反射的方式生成javabean实例,返回即可

完整代码如下:

package com.huajie.day1.xml.spring;

import java.io.InputStream;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ClassPathXmlApplicationContext {
	private String xmlPath;

	public ClassPathXmlApplicationContext(String xmlPath) {
		this.xmlPath = xmlPath;
		initBeans();
	}

	private void initBeans() {
		// 获取xml中 对象的 ClassPath

		// 反射方式创建对象
	}

	public Object getBean(String beanId) throws Exception {
		if (StringUtils.isEmpty(beanId)) {
			throw new RuntimeException("beanId不能为空");
		}
		// 获取xml文件中所有的Bean节点信息
		List<Element> liste = readerXML();
		if (liste == null || liste.isEmpty()) {
			throw new RuntimeException("配置文件中没有bean的信息");
		}
		String className = getBeanClassNameById(liste, beanId);
		if (StringUtils.isEmpty(className)) {
			throw new RuntimeException("类路径错误");
		}
		return newInstance(className);
	}

	private String getBeanClassNameById(List<Element> liste, String beanId){
		// 遍历节点获取bean
		for (Element element : liste) {
			String xmlBeanId = element.attributeValue("id");
			if (StringUtils.isEmpty(xmlBeanId)) {
				continue;
			}
			if (beanId.equals(xmlBeanId)) {
				String className = element.attributeValue("class");
				return className;
			}
		}
		return null;
	}

	public Object newInstance(String className) {
		try {
			return Class.forName(className).newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	// 解析xml文件
	public List<Element> readerXML() throws DocumentException {

		SAXReader saxReader = new SAXReader();
		Document read = saxReader.read(getClassPath(xmlPath));
		// 获取根节点
		Element rootElement = read.getRootElement();
		List<Element> listnodes = rootElement.elements();
		return listnodes;

	}

	// 获取当前上下文路径
	public InputStream getClassPath(String xmlPath) {
		InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(xmlPath);
		return resourceAsStream;
	}

}

6.相关的测试代码文件

package com.huajie.day1.impl;

import org.springframework.stereotype.Service;
import com.huajie.day1.UserService;


@Service("userService")
public class UserServiceImpl implements UserService {

	public int add(String a) {
		System.out.println("添加");
		return 0;
	}

}
package com.huajie.day1;

import com.huajie.day1.xml.spring.ClassPathXmlApplicationContext;

public class Test001 {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("user-annotation.xml");
		UserService userService = null;
		try {
			userService = (UserService)app.getBean("userService");
		} catch (Exception e) {
			e.printStackTrace();
		}
		userService.add("1");
	}

}

package com.huajie.day1;

import org.springframework.stereotype.Service;

public interface UserService {
    int add(String a);
}

7.pom.xml文件需要引入dom4j的依赖

<!-- https://mvnrepository.com/artifact/dom4j/dom4j -->
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.6</version>
		</dependency>

注意:由于是测试版本,xml配置文件和test001.java文件是在同一目录下面


测试效果如下:




猜你喜欢

转载自blog.csdn.net/xiewenfeng520/article/details/80937947