zoukankan      html  css  js  c++  java
  • [转]spring注入原理

    [转]spring注入原理

    转载:http://blog.csdn.net/zhikun518/article/details/7185499

     

    IOC(Inverse of Control)可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”。在Spring中,通过IOC可以将实现类 、参数信息等配置在其对应的配置文件中 ,那么当需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合。我们还可以对某对象所需要的其它对象进行注入 ,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制,Spring还充当了工厂的角色,我们不需要自己建立工厂类 。Spring的工厂类会帮我们完成配置文件的读取、利用反射机制注入对象等工作,我们可以通过bean的名称获取对应的对象。下面让我们看看如下的模拟Spring的bean工厂类:

    1、BeanFactory.java

    1. package com.yt.manager.spring;  
    2.   
    3. import java.io.InputStream;  
    4. import java.lang.reflect.Method;  
    5. import java.util.HashMap;  
    6. import java.util.Iterator;  
    7. import java.util.Map;  
    8. import org.apache.log4j.Logger;  
    9. import org.dom4j.Attribute;  
    10. import org.dom4j.Document;  
    11. import org.dom4j.Element;  
    12. import org.dom4j.io.SAXReader;  
    13.   
    14. /** 
    15.  * @ClassName: BeanFactory 
    16.  * @Project: base-info 
    17.  * @Author: zxf 
    18.  * @Date: 2011-5-19 
    19.  */  
    20. public class BeanFactory {  
    21.       
    22.     Logger log = Logger.getLogger(BeanFactory.class);  
    23.     private Map<String, Object> beanMap = new HashMap<String, Object>();  
    24.   
    25.     /** 
    26.      * bean工厂的初始化 
    27.      *  
    28.      * @param xml 
    29.      */  
    30.     public void init(String xml) {  
    31.         try {  
    32.             //读取指定的配置文件  
    33.             SAXReader reader = new SAXReader();  
    34.             //从class目录下获取指定的配置文件  
    35.             ClassLoader classLoader = Thread.currentThread().getContextClassLoader();  
    36.             InputStream inputStream = classLoader.getResourceAsStream(xml);  
    37.             //读取xml文件  
    38.             Document document = reader.read(inputStream);  
    39.             //获取跟节点  
    40.             Element root = document.getRootElement();  
    41.             //遍历bean节点  
    42.             Element foo;  
    43.             for(Iterator iteBean = root.elementIterator("bean");iteBean.hasNext();){  
    44.                 foo = (Element)iteBean.next();  
    45.                 //获取bean的属性id和class  
    46.                 Attribute id = foo.attribute("id");  
    47.                 Attribute cls = foo.attribute("class");  
    48.                 //利用java反射机制,通过class的名称获取Class对象  
    49.                 Class bean = Class.forName(cls.getText());  
    50.                 //获取对应class信息  
    51.                 java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);  
    52.                 //获取其属性描述  
    53.                 java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();  
    54.                 //设置值的方法  
    55.                 Method mSet = null;  
    56.                 //创建一个对象(创建此 Class 对象所表示的类的一个新实例。如同用一个带有一个空参数列表的 new 表达式实例化该类。如果该类尚未初始化,则初始化这个类。)  
    57.                 Object obj = bean.newInstance();  
    58.                   
    59.                 //遍历该bean的property属性  
    60.                 for(Iterator iteProperty = foo.elementIterator("property");iteProperty.hasNext();){  
    61.                     Element elementProperty = (Element)iteProperty.next();  
    62.                     //获取该property的name属性  
    63.                     Attribute name = elementProperty.attribute("name");  
    64.                     String value = null;  
    65.                     //获取该property的子元素value的值  
    66.                     for(Iterator iteValue = elementProperty.elementIterator("value");iteValue.hasNext();){  
    67.                         Element elementValue = (Element)iteValue.next();  
    68.                         value = elementValue.getText();  
    69.                         break;  
    70.                     }  
    71.                       
    72.                     for (int k = 0; k < pd.length; k++) {  
    73.                         log.info(pd[k].getName());  
    74.                         if (pd[k].getName().equalsIgnoreCase(name.getText())) {  
    75.                                mSet = pd[k].getWriteMethod();  
    76.                                //利用Java的反射机制调用对象的某个set方法,并将值设置进去  
    77.                                mSet.invoke(obj, value);  
    78.                         }  
    79.                  }  
    80.                 }  
    81.                //将对象放入beanMap中,其中key为id值,value为对象  
    82.                 beanMap.put(id.getText(), obj);  
    83.             }  
    84.   
    85.         } catch (Exception e) {  
    86.             e.printStackTrace();  
    87.         }  
    88.     }  
    89.       
    90.     /** 
    91.      * 通过bean的id获取bean的对象. 
    92.      * @param beanName bean的id 
    93.      * @return 返回对应对象 
    94.      */  
    95.      public Object getBean(String beanName) {  
    96.            Object obj = beanMap.get(beanName);  
    97.            return obj;  
    98.      }  
    99.   
    100.      public static void main(String[] args) {  
    101.          BeanFactory factory = new BeanFactory();  
    102.          factory.init("config.xml");  
    103.          JavaBean javaBean = (JavaBean) factory.getBean("javaBean");  
    104.          System.out.println("userName=" + javaBean.getUserName());  
    105.          System.out.println("password=" + javaBean.getPassWord());  
    106.      }  
    107. }  

     2、JavaBean.java

    1. package com.yt.manager.spring;  
    2.   
    3. /** 
    4.  * @Description: 
    5.  * @ClassName: JavaBean 
    6.  * @Project: base-info 
    7.  * @Author: zxf 
    8.  * @Date: 2011-5-19 
    9.  */  
    10. public class JavaBean {  
    11.     private String userName;  
    12.     private String passWord;  
    13.   
    14.     public String getUserName() {  
    15.         return userName;  
    16.     }  
    17.   
    18.     public void setUserName(String userName) {  
    19.         this.userName = userName;  
    20.     }  
    21.   
    22.     public String getPassWord() {  
    23.         return passWord;  
    24.     }  
    25.   
    26.     public void setPassWord(String passWord) {  
    27.         this.passWord = passWord;  
    28.     }  
    29.   
    30. }  

     3、config.xml

    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans>  
    3.     <bean id = "javaBean" class="com.yt.manager.spring.JavaBean">  
    4.         <property name="userName">  
    5.             <value>这是姓名</value>  
    6.         </property>  
    7.         <property name="passWord">  
    8.             <value>这是密码</value>  
    9.         </property>  
    10.     </bean>  
    11. </beans>  

          可以看到,虽然在main()方法中没有对属性赋值,但属性值已经被注入,在BeanFactory类中的Class bean = Class.forName(cls.getText()); 通过类名来获取对应的类,mSet.invoke(obj, value);通过invoke方法来调用特定对象的特定方法,实现的原理都是基于Java的反射机制,在此我们有一次见证了Java反射机制的强大。当然,这只是对IOC的一个简单演示,在Spring中,情况要复杂得多,例如,可以一个bean引用另一个bean,还可以有多个配置文件、通过多种方式载入配置文件等等。不过原理还是采用Java的反射机制来实现IOC的。
           在本文中,笔者通过讲述Java反射机制概述与初探、IOC使用的背景、IOC粉墨登场等内容,演示了Java反射机制API的强大功能,并通过编写自己的简单的IOC框架,让读者更好的理解了IOC的实现原理。本文通过IOC的一个简要实现实例,模拟了Spring中IOC的实现,虽然只是完成了Spring中依赖注入的一小部分工作, 但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现,也能为我们实现自己的准Spring框架提供方案,有兴趣的朋友可以通过Spring的源码进行IOC的进一步的学习。

      附:通过java反射机制获取指定类的属性和方法

    1. package com.yt.manager.spring;  
    2.   
    3. import java.beans.BeanInfo;  
    4. import java.beans.Introspector;  
    5. import java.beans.MethodDescriptor;  
    6. import java.beans.PropertyDescriptor;  
    7.   
    8. /** 
    9.  * @Description:java.beans包的使用 
    10.  * @ClassName: JavaBeans 
    11.  * @Project: base-info 
    12.  * @Author: zxf 
    13.  * @Date: 2011-5-19 
    14.  */  
    15. public class JavaBeans {  
    16.   
    17.     /** 
    18.      * @param args 
    19.      * @throws Exception 
    20.      */  
    21.     @SuppressWarnings("rawtypes")  
    22.     public static void main(String[] args) throws Exception {  
    23.         // 返回与带有给定字符串名的类或接口相关联的 Class 对象  
    24.         Class bean = Class.forName("com.yt.manager.spring.JavaBean");  
    25.         // 获取指定类的信息  
    26.         BeanInfo info = Introspector.getBeanInfo(bean);  
    27.         // 遍历指定类的方法  
    28.         MethodDescriptor[] methods = info.getMethodDescriptors();  
    29.         for (int i = 0; i < methods.length; i++) {  
    30.             System.out.println("方法:"+methods[i].getDisplayName());  
    31.         }  
    32.         // 遍历指定类的属性  
    33.         PropertyDescriptor[] propertys = info.getPropertyDescriptors();  
    34.         for (int j = 0; j < propertys.length; j++) {  
    35.             System.out.println("属性:"+propertys[j].getName());  
    36.         }  
    37.     }  
    38.   
    39. }  
     
    1. package com.yt.manager.spring;  
    2.   
    3. import java.lang.reflect.Method;  
    4.   
    5. /** 
    6.  * @Description: java.lang.reflect.method类中invoke方法的使用 
    7.  * @ClassName: MethodInvoke 
    8.  * @Project: base-info 
    9.  * @Author: zxf 
    10.  * @Date: 2011-5-19 
    11.  */  
    12. public class MethodInvoke {  
    13.   
    14.     /**  
    15.      * @param args 
    16.      * @throws ClassNotFoundException 
    17.      */  
    18.     public static void main(String[] args) throws Exception {  
    19.           
    20.         JavaBean javaBean = new JavaBean();  
    21.         //获取指定类的指定方法,  
    22.         Class c = Class.forName("com.yt.manager.spring.JavaBean");  
    23.         Method method = c.getMethod("setUserName"new Class[] { String.class });  
    24.         //对带有指定参数的指定对象调用由此 Method 对象表示的底层方法,调用对象javaBean的setuserName方法,参数为"testName"  
    25.         method.invoke(javaBean, "testName");  
    26.           
    27.         System.out.println(javaBean.getUserName());  
    28.     }  
    29.   
    30. }
  • 相关阅读:
    ZOJ 3765 Lights (zju March I)伸展树Splay
    UVA 11922 伸展树Splay 第一题
    UVALive 4794 Sharing Chocolate DP
    ZOJ 3757 Alice and Bod 模拟
    UVALive 3983 捡垃圾的机器人 DP
    UVA 10891 SUM游戏 DP
    poj 1328 Radar Installatio【贪心】
    poj 3264 Balanced Lineup【RMQ-ST查询区间最大最小值之差 +模板应用】
    【转】RMQ-ST算法详解
    poj 3083 Children of the Candy Corn 【条件约束dfs搜索 + bfs搜索】【复习搜索题目一定要看这道题目】
  • 原文地址:https://www.cnblogs.com/zjhs/p/2695177.html
Copyright © 2011-2022 走看看