本身动手编写spring IOC源码

前言:对于spring IOC概念不是很了解的朋友能够阅读我上一篇博客——轻松理解spring IOC(这两篇博客也是因为个人我的缘由致使如今才发布,惭愧啊)。经过这篇博客的理解以后,相信你们会对spring的IOC概念会有进一步的理解。接下来我先预览一下本例中java的类图关系。html

解析:咱们有一个Master接口,接口中定义了一个WalkDog()遛狗的方法,Hostess是对这个接口的具体实现。而后咱们有一个Dog接口,接口中有一个bark()方法,Labuladuo和Taidi是对其的实现。最后咱们的程序入口Client类调用Hostess对象的WalkDog方法。java

需求:Hostess对象遛狗须要一个狗对象,目前咱们的类中有两个符合需求的对象,咱们只要在配置文件中进行相关配置即可以指定咱们的Hostess对象调用的是哪个具体的Dog对象。算法

 1 public static void main(String[] args) {
 2         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
 3         Master master = (Master)context.getBean("hostess");
 4         
 5         System.out.println();
 6         System.out.println();
 7         System.out.println();
 8         System.out.println("***********************************");
 9         master.WalkDog();
10     }

解析:从main方法的前两句原spring的代码中咱们能够猜测,spring框架中必定是定义了ApplicationContext这个接口,而且接口中定义了一个getBean()的方法,而ClassPathXmlApplicationContext类确定是对其的实现。既然是咱们本身动手写spring框架,咱们把这个接口和类实现了也就能够了。spring

接口 ApplicationContext 安全

1 public interface ApplicationContext {
2     public Object getBean(String beanid);
3 }

实现类 ClassPathXmlApplicationContextapp

 1 package com;
 2 
 3 import java.io.File;
 4 import java.lang.reflect.Method;
 5 
 6 import org.dom4j.Document;
 7 import org.dom4j.DocumentException;
 8 import org.dom4j.Element;
 9 import org.dom4j.Node;
10 import org.dom4j.io.SAXReader;
11 
12 public class ClassPathXmlApplicationContext implements ApplicationContext {
13 
14     private String fileName;
15     
16     public ClassPathXmlApplicationContext(String fileName){
17         this.fileName = fileName;
18     }
19     
20     @Override
21     public Object getBean(String beanid) {
22         //获取本类的当前目录
23         String currentPath = this.getClass().getResource("").getPath().toString();
24         
25         SAXReader reader = new SAXReader();//DOM4J解释器
26         Document doc = null;//xml文档自己
27         Object obj = null;//目标表建立出来的实例
28         try {
29             doc = reader.read(  new File(currentPath+fileName)  );
30             String xpath = "/beans/bean[@id='"+beanid+"']";
31             Element beanNode = (Element) doc.selectSingleNode(xpath);
32             String className = beanNode.attributeValue("class");
33             obj = Class.forName(className).newInstance();
34             
35             Element propertyNode = (Element) beanNode.selectSingleNode("property");
36             
37             if(propertyNode!=null){
38                 System.out.println("当前bean有属性须要注入");
39                 
40                 String propertyName = propertyNode.attributeValue("name");
41                 System.out.println("当前bean须要注入的属性为"+propertyName);
42                 
43                 //拼接出注入方法
44                 String setMethod = "set"+(propertyName.substring(0, 1)).toUpperCase()+propertyName.substring(1,propertyName.length());
45                 System.out.println("自动调用注入方法"+setMethod);
46                 
47                 String set_object_name = propertyNode.attributeValue("ref");
48                 System.out.println("须要注入的对象名"+set_object_name);
49                 
50                 Object di_object = getBean(set_object_name);
51                 System.out.println("注入的对象实例"+di_object);
52                 
53                 Method []methods = obj.getClass().getMethods();
54                 
55                 for (Method m : methods) {
56                     if(setMethod.equals(m.getName())  ) {
57                         m.invoke(obj, di_object);
58                         break;
59                     }
60                 }
61                 
62             }else{
63                 System.out.println("当前bean没有属性,无需注入直接结束");
64             }
65             
66         } catch (Exception e) {
67             e.printStackTrace();
68         }
69         
70         
71         return obj;
72     }
73 
74 }

配置文件 applicationContext.xml框架

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans>
 3     <bean id="hostess" class="com.Hostess">
 4         <property name="dog" ref="Taidi_dog"></property>
 5     </bean>
 6     
 7     <bean id="Taidi_dog" class="com.Taidi"></bean>
 8     
 9     <bean id="Labuladuo_dog" class="com.Labuladuo"></bean>
10 </beans>

解析:① 咱们的applicationContext.xml文件主要是配置咱们的java bean。这里咱们本身写一份这样的文件通知咱们本身的框架有哪些对象须要注入。dom

② 接口 ApplicationContext 这里我只是定义了一个方法就很少解释了。ide

③ 实现类 ClassPathXmlApplicationContext 主要是解析咱们的xml文件而后构造实例的一个类。解析xml文件咱们主要使用的是dom4j,获取各个节点和节点属性与属性值。建立对象则是经过反射的方式构造对象 [obj = Class.forName(className).newInstance();]。 在判断一个对象是否有属性须要注入则是使用递归算法对其一一注入。this

最后: 咱们来看一下运行结果

小结:咱们本身手写的框架天然没有spring框架严谨,安全(否则它早倒闭了),不过spring的原理咱们本身的也是大同小异的。经过源码级别的解读,相信你们已经能够熟练掌握IOC原理。

相关文章
相关标签/搜索