!!!
这只是我为了学习Spring而写的内容,和真正的Spring比起来少了很多很多,只是使用了Spring的一些思想去模拟他得到一些功能,大家可以看懂我的实现方式,然后再去看Spring的源码会简单很多。
public class MySpring {
private Myreference reference;
public void setReference(Myreference reference) {
this.reference = reference;
}
}
public class Myreference {
public void show(){
System.out.println("我是注入进来的依赖");
}
}
好了我们现在开始写工厂类,工厂类中会实现xml文件的读取和解析,bean的实例化以及存储,还有bean中的依赖注入
第一步,读取xml文件,为我们需要导入两个工具类,jaxen和dom4j
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
创建一个工厂包,建立一个BeanFactory类
/**
* 工厂类 生产对象 使用反射技术
*/
public class BeanFactory {
private static Map<String, Object> map = new HashMap<String, Object>();//存储对象
?
/*
类加载的时候就执行
*/
static {
//将配置文件读取成流
InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");
//开始解析xml
SAXReader saxReadeer = new SAXReader();
try {
Document document = saxReadeer.read(inputStream);
Element rootElement = document.getRootElement();//获取根元素
List<Element> beanList = rootElement.selectNodes("//bean");//获取所有bean标签
?
for (Element element : beanList) {
String id = element.attributeValue("id"); //myspring
String claszz = element.attributeValue("class"); //com.william.entity.MySpring
Class<?> aClass = Class.forName(claszz);
Object o = aClass.newInstance(); //获取一个实例
?
map.put(id,o);//将这个id和类对象放到对象池中,类似于spring中的单例池
}
?
//实例化完成之后维护对象依赖
List<Element> propertyList = rootElement.selectNodes("//property");
//解析property,获取父元素
for (int i = 0; i < propertyList.size(); i++) {
Element element = propertyList.get(i); //<property name ="Reference" ref="myreference"></property>
String name = element.attributeValue("name");
String ref = element.attributeValue("ref");
?
//找到这个元素的上级,即需要注入依赖的元素
Element parent = element.getParent();
//调用父元素反射
String parentId = parent.attributeValue("id");
Object parentObject = map.getOrDefault(parentId, null);//获取到这个父类
Method[] methods = parentObject.getClass().getMethods();
for (Method method : methods) {//定位到set方法,使用set注入
if(method.getName().equalsIgnoreCase("set"+name)){
method.invoke(parentObject,map.get(ref));
}
}
?
//把父元素更新
map.put(parentId,parentObject);
}
}