
- 前言
- 一、框架实现原理图解
- 二、仿Spring实现简易IOC机制
- 1、设计 *** 作Bean的相关数据结构
- 1、 *** 作bean的基础数据结构BeanDefinition
- 2、bean的引用类(Ref)
- 3、Bean属性值类
- 4、Bean属性值实体集合类
- 2、设计实现资源加载器接口
- 1、定义一个资源输入接口
- 2、实现资源接口
- 3、实现一个资源加载器
- 3、设计实现XML文件解析器
- 1、设计BeanDefinition读取接口
- 2、设计定义一个BeanDefinition读取的抽象类
- 4、设计实现Bean的自动生成工厂
- 1、定义一个beanFactory
- 2、定义一个beanFactory的抽象类
- 3、实现BeanFactory具体创建功能
- 5、编写测试
- 1、定义一个HelloWorld实体
- 2、定义一个引用HelloWorld实体的实体
- 3、resource文件夹下编写XML文件
- 4、编写测试类
- 总结
前言
在Spring框架中,IOC控制反转机制是其中的核心概念,为深入理解Spring中IOC的原理、实现机制,学习仿SpringIOC搭建简易版本。
一、框架实现原理图解 二、仿Spring实现简易IOC机制 1、设计 *** 作Bean的相关数据结构 1、 *** 作bean的基础数据结构BeanDefinition
package com.huangjunli.beandefinition;
public class BeanDefinition {
private Object bean;
private Class beanClass;
private String ClassName;
private PropertyValues propertyValues = new PropertyValues();
public Object getBean() {
return this.bean;
}
public void setBean(Object bean) {
this.bean = bean;
}
public Class getBeanclass() {
return this.beanClass;
}
public void setClassname(String name) {
this.ClassName = name;
try {
this.beanClass = Class.forName(name);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public PropertyValues getPropertyValues() {
return this.propertyValues;
}
public void setPropertyValues(PropertyValues pv) {
this.propertyValues = pv;
}
}
2、bean的引用类(Ref)
package com.huangjunli.beandefinition;
public class BeanReference {
private String name;
private Object bean;
public BeanReference(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setBean(Object bean) {
this.bean = bean;
}
public Object getBean() {
return this.bean;
}
}
3、Bean属性值类
package com.huangjunli.beandefinition;
public class PropertyValue {
private final String name;
private final Object value;
public PropertyValue(String name, Object value) {
this.name = name;
this.value = value;
}
public String getname() {
return this.name;
}
public Object getvalue() {
return this.value;
}
}
4、Bean属性值实体集合类
package com.huangjunli.beandefinition;
import java.util.ArrayList;
import java.util.List;
public class PropertyValues {
private final List propertyValueList = new ArrayList<>();
public PropertyValues() {
}
public void addPropertyValue(PropertyValue pv) {
propertyValueList.add(pv);
}
public List getPropertyValues() {
return propertyValueList;
}
}
2、设计实现资源加载器接口
1、定义一个资源输入接口
通过该接口获取到指定资源的输入流对象。
package com.huangjunli.io;
import java.io.InputStream;
public interface Resource {
InputStream getInputstream() throws Exception;
}
2、实现资源接口
package com.huangjunli.io;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class ResourceUrl implements Resource {
private final URL url;
public ResourceUrl(URL url) {
this.url = url;
}
@Override
public InputStream getInputstream() throws Exception {
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
return urlConnection.getInputStream();
}
}
3、实现一个资源加载器
通过资源加载器获取资源,提供给XML文件读取使用。
package com.huangjunli.io;
import java.net.URL;
public class ResourceLoader {
public ResourceUrl getResource(String location) {
URL url = this.getClass().getClassLoader().getResource(location);
return new ResourceUrl(url);
}
}
3、设计实现XML文件解析器
1、设计BeanDefinition读取接口
package com.huangjunli.xml;
public interface BeanDefinitionReader {
}
2、设计定义一个BeanDefinition读取的抽象类
该类定义两个重要属性:其一为注册bean的容器;其二为资源获取的接口对象。
package com.huangjunli.xml;
import com.huangjunli.beandefinition.BeanDefinition;
import com.huangjunli.io.ResourceLoader;
import java.util.HashMap;
import java.util.Map;
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader {
private Map registry;
private ResourceLoader resourceLoader;
protected AbstractBeanDefinitionReader(ResourceLoader resourceLoader) {
this.registry = new HashMap<>();
this.resourceLoader = resourceLoader;
}
public Map getRegistry() {
return registry;
}
public ResourceLoader getResourceLoader() {
return resourceLoader;
}
}
3、实现读取XML配置文件的具体方法及解析bean到注册容器中
package com.huangjunli.xml;
import com.huangjunli.beandefinition.BeanDefinition;
import com.huangjunli.beandefinition.BeanReference;
import com.huangjunli.beandefinition.PropertyValue;
import com.huangjunli.io.ResourceLoader;
import org.w3c.dom.document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.documentBuilder;
import javax.xml.parsers.documentBuilderFactory;
import java.io.InputStream;
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
public XmlBeanDefinitionReader(ResourceLoader resourceLoader) {
super(resourceLoader);
}
public void readerXML(String location) throws Exception {
// 创建一个资源加载器
ResourceLoader resourceloader = new ResourceLoader();
// 从资源加载器中获取输入流
InputStream inputstream = resourceloader.getResource(location).getInputstream();
// 获取文档建造者工厂实例
documentBuilderFactory factory = documentBuilderFactory.newInstance();
// 工厂创建文档建造者
documentBuilder docBuilder = factory.newdocumentBuilder();
// 文档建造者解析流 返回文档对象
document doc = docBuilder.parse(inputstream);
// 根据给定的文档对象进行解析,并注册到bean容器中
registerBeanDefinitions(doc);
// 关闭流
inputstream.close();
}
private void registerBeanDefinitions(document doc) {
// 读取文档的根元素
Element root = doc.getdocumentElement();
// 解析元素的根节点及根节点下的所有子节点并添加进注册容器
parseBeanDefinitions(root);
}
private void parseBeanDefinitions(Element root) {
// 读取根元素的所有子元素
NodeList nl = root.getChildNodes();
// 遍历子元素
for (int i = 0; i < nl.getLength(); i++) {
// 获取根元素的给定位置的节点
Node node = nl.item(i);
// 类型判断
if (node instanceof Element) {
// 强转为父类型元素
Element ele = (Element) node;
// 解析给给定的节点,包括name,class,property, name, value,ref
processBeanDefinition(ele);
}
}
}
private void processBeanDefinition(Element ele) {
// 获取给定元素的 name 属性
String name = ele.getAttribute("name");
// 获取给定元素的 class 属性
String className = ele.getAttribute("class");
// 创建一个bean定义对象
BeanDefinition beanDefinition = new BeanDefinition();
// 设置bean 定义对象的 全限定类名
beanDefinition.setClassname(className);
// 向 bean 注入配置文件中的成员变量
addPropertyValues(ele, beanDefinition);
// 向注册容器 添加bean名称和bean定义
getRegistry().put(name, beanDefinition);
}
private void addPropertyValues(Element ele, BeanDefinition beandefinition) {
// 获取给定元素的 property 属性集合
NodeList propertyNode = ele.getElementsByTagName("property");
// 循环集合
for (int i = 0; i < propertyNode.getLength(); i++) {
// 获取集合中某个给定位置的节点
Node node = propertyNode.item(i);
// 类型判断
if (node instanceof Element) {
// 将节点向下强转为子元素
Element propertyEle = (Element) node;
// 元素对象获取 name 属性
String name = propertyEle.getAttribute("name");
// 元素对象获取 value 属性值
String value = propertyEle.getAttribute("value");
// 判断value不为空
if (value != null && value.length() > 0) {
// 向给定的 “bean定义” 实例中添加该成员变量
beandefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value));
} else {
// 如果为空,则获取属性ref
String ref = propertyEle.getAttribute("ref");
if (ref == null || ref.length() == 0) {
// 如果属性ref为空,则抛出异常
throw new IllegalArgumentException(
"Configuration problem: element for property '"
+ name + "' must specify a ref or value");
}
// 如果不为空,测创建一个 “bean的引用” 实例,构造参数为名称,实例暂时为空
BeanReference beanRef = new BeanReference(name);
// 向给定的 “bean定义” 中添加成员变量
beandefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanRef));
}
}
}
}
}
4、设计实现Bean的自动生成工厂
1、定义一个beanFactory
该接口提供两个功能:其一获取bean;其二注册bean。
package com.huangjunli.factory;
import com.huangjunli.beandefinition.BeanDefinition;
public interface BeanFactory {
Object getBean(String name) throws Exception;
void registerBeanDefinition(String name, BeanDefinition bean) throws Exception;
}
2、定义一个beanFactory的抽象类
该类定义一个创建bean实例的抽象方法。
package com.huangjunli.factory;
import com.huangjunli.beandefinition.BeanDefinition;
import java.util.HashMap;
public abstract class AbstractBeanFactory implements BeanFactory {
private HashMap map = new HashMap<>();
@Override
public Object getBean(String name) throws Exception {
BeanDefinition beandefinition = map.get(name);
if (beandefinition == null) {
throw new IllegalArgumentException("No bean named " + name + " is defined");
}
Object bean = beandefinition.getBean();
if (bean == null) {
bean = doCreate(beandefinition);
}
return bean;
}
@Override
public void registerBeanDefinition(String name, BeanDefinition beandefinition) throws Exception {
Object bean = doCreate(beandefinition);
beandefinition.setBean(bean);
map.put(name, beandefinition);
}
abstract Object doCreate(BeanDefinition beandefinition) throws Exception;
}
3、实现BeanFactory具体创建功能
package com.huangjunli.factory;
import com.huangjunli.beandefinition.BeanDefinition;
import com.huangjunli.beandefinition.BeanReference;
import com.huangjunli.beandefinition.PropertyValue;
import java.lang.reflect.Field;
public class AutowireBeanFactory extends AbstractBeanFactory {
@Override
protected Object doCreate(BeanDefinition beandefinition) throws Exception {
Object bean = beandefinition.getBeanclass().newInstance();
addPropertyValue(bean, beandefinition);
return bean;
}
protected void addPropertyValue(Object bean, BeanDefinition beandefinition) throws Exception {
// 循环给定 bean 的属性集合
for (PropertyValue pv : beandefinition.getPropertyValues().getPropertyValues()) {
// 根据给定属性名称获取 给定的bean中的属性对象
Field declaredField = bean.getClass().getDeclaredField(pv.getname());
// 设置属性的访问权限
declaredField.setAccessible(true);
// 获取定义的属性中的对象
Object value = pv.getvalue();
// 判断这个对象是否是 BeanReference 对象
if (value instanceof BeanReference) {
// 将属性对象转为 BeanReference 对象
BeanReference beanReference = (BeanReference) value;
// 调用父类的 AbstractBeanFactory 的 getBean 方法,根据bean引用的名称获取实例,此处即是递归
value = getBean(beanReference.getName());
}
// 反射注入bean的属性
declaredField.set(bean, value);
}
}
}
5、编写测试
1、定义一个HelloWorld实体
package com.huangjunli.test;
public class HelloWorld {
private String text;
void say() {
System.out.println(text);
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
2、定义一个引用HelloWorld实体的实体
package com.huangjunli.test;
public class ReferenceBean {
private HelloWorld hello;
public void say() {
hello.say();
}
public void setHello(HelloWorld hello) {
this.hello = hello;
}
}
3、resource文件夹下编写XML文件
文件名随意,与读取时传入的参数匹配即可。
xml.readerXML("myspring.xml");
4、编写测试类
package com.huangjunli.test;
import com.huangjunli.beandefinition.BeanDefinition;
import com.huangjunli.factory.AutowireBeanFactory;
import com.huangjunli.factory.BeanFactory;
import com.huangjunli.io.ResourceLoader;
import com.huangjunli.xml.XmlBeanDefinitionReader;
import org.junit.Test;
import java.util.Map;
public class XmlBeanDefinitionReaderTest {
@Test
public void test() throws Exception {
// 创建一个XML解析器,携带一个资源加载器
XmlBeanDefinitionReader xml = new XmlBeanDefinitionReader(new ResourceLoader());
// 解析该文件
xml.readerXML("myspring.xml");
// 创建一个自动注入bean工厂
BeanFactory beanfactory = new AutowireBeanFactory();
// 循环xml中的所有bean
for (Map.Entry beanDefinitionEntry : xml.getRegistry().entrySet()) {
// 将XML容器中的bean注册到bean工厂
beanfactory
.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue());
}
// 获取持有另一个bean对象的bean(也是从容器中取得的)
ReferenceBean hello = (ReferenceBean) beanfactory.getBean("referenceBean");
// 调用对象方法
hello.say();
}
}
总结
springIOC的原理并不复杂,简单回顾一下实现步骤:
- 通过XML文件读取bean信息
- 解析加载bean信息到注册容器中
- bean工厂底层通过反射完成bean实例的创建
当然spring中的实现需要考虑其他如性能、安全等各方面的因素,因而实现复杂很多。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)