Spring-依赖注入原理

使用构造器注入
使用属性setter方法注入
使用Field注入(用于注解方式)

注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。

1.手工装配依赖对象
2.自动装配依赖对象


Spring学习笔记(3)中剖析了Spring管理Bean的原理,下面解释下Spring依赖注入的原理

在进行依赖注入时,我们的配置文件如下配置:

Xml代码 
  
http://www.springframework.org/schema/beans
"  
    xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:context="
http://www.springframework.org/schema/context"  
    xmlns:tx="
http://www.springframework.org/schema/tx"  
    xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
                
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd   
                
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
      
      
      
          
          
   
  
 


http://www.springframework.org/schema/beans
"
 xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="
http://www.springframework.org/schema/context"
 xmlns:tx="
http://www.springframework.org/schema/tx"
 xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
 
 
 
  
  
 


 
根据配置文件信息,我们首先需要建立一个Bean类,用来保存bean节点的信息:

Java代码 
package com.szy.spring.bean;   
  
import java.util.List;   
  
public class Bean   
{   
    private String id;      
    private String className;    
    private List propertyList;   
    public Bean(String id, String className, List propertyList)   
    {   
        super();   
        this.id = id;   
        this.className = className;   
        this.propertyList = propertyList;   
    }   
    public String getId()      
    {      
        return id;      
    }      
    public void setId(String id)      
    {      
        this.id = id;      
    }      
    public String getClassName()      
    {      
        return className;      
    }      
    public void setClassName(String className)      
    {      
        this.className = className;      
    }   
    public List getPropertyList()   
    {   
        return propertyList;   
    }   
    public void setPropertyList(List propertyList)   
    {   
        this.propertyList = propertyList;   
    }      

package com.szy.spring.bean;

import java.util.List;

public class Bean
{
 private String id;   
    private String className; 
    private List propertyList;
 public Bean(String id, String className, List propertyList)
 {
  super();
  this.id = id;
  this.className = className;
  this.propertyList = propertyList;
 }
 public String getId()   
    {   
        return id;   
    }   
    public void setId(String id)   
    {   
        this.id = id;   
    }   
    public String getClassName()   
    {   
        return className;   
    }   
    public void setClassName(String className)   
    {   
        this.className = className;   
    }
 public List getPropertyList()
 {
  return propertyList;
 }
 public void setPropertyList(List propertyList)
 {
  this.propertyList = propertyList;
 }   
}
 
此外,由于bean下存在property信息,因此我们还需要建立property

Java代码 
package com.szy.spring.bean;   
  
public class Property   
{   
    private String name;   
    private String ref;   
       
    public Property(String name, String ref)   
    {   
        super();   
        this.name = name;   
        this.ref = ref;   
    }   
    public String getName()   
    {   
        return name;   
    }   
    public void setName(String name)   
    {   
        this.name = name;   
    }   
    public String getRef()   
    {   
        return ref;   
    }   
    public void setRef(String ref)   
    {   
        this.ref = ref;   
    }   
       

package com.szy.spring.bean;

public class Property
{
 private String name;
 private String ref;
 
 public Property(String name, String ref)
 {
  super();
  this.name = name;
  this.ref = ref;
 }
 public String getName()
 {
  return name;
 }
 public void setName(String name)
 {
  this.name = name;
 }
 public String getRef()
 {
  return ref;
 }
 public void setRef(String ref)
 {
  this.ref = ref;
 }
 
}
 

Spring学习笔记(3)中,我们在读取xml文件时bean节点下面是不存在property节点的,因此在这里我们需要修改readXML()方法:

Java代码 
/**  
     *
读取xml配置文件  
     * @param fileName
配置文件名  
     */  
    private void readXML(String fileName)   
    {   
        //
寻找配置文件   
        URL xmlPath = this.getClass().getClassLoader().getResource(fileName);   
        Document doc = null;   
        Element root = null;   
        try  
        {   
            SAXBuilder sb = new SAXBuilder(false);   
            doc = sb.build(new FileInputStream(new File(xmlPath.toURI())));   
            //
设置命名空间      
            Namespace xhtml = Namespace.getNamespace("xhtml",   
                    "
http://www.springframework.org/schema/beans");   
            root = doc.getRootElement(); //
获取根元素      
            List bList = root.getChildren("bean", xhtml); //
获取全部bean节点      
            for (Element beanElement : bList)//
遍历节点,取得每个节点的属性      
            {   
                String id = beanElement.getAttributeValue("id");   
                String className = beanElement.getAttributeValue("class");   
                //
获得每个bean下面的属性   
                List pList = beanElement   
                        .getChildren("property", xhtml);   
                List propertyList = new ArrayList(); //
存储属性信息   
                if (pList.size() > 0) //
如果存在属性   
                {   
                    for (Element propertyElement : pList) //
遍历属性节点   
                    {   
                        String name = propertyElement.getAttributeValue("name");   
                        String ref = propertyElement.getAttributeValue("ref");   
                        Property property = new Property(name, ref);   
                        propertyList.add(property); //
保存属性节点   
                    }   
                }   
                Bean bean = new Bean(id, className, propertyList);   
                beanList.add(bean);   
            }   
  
        } catch (Exception e)   
        {   
            e.printStackTrace();   
        }   
    } 

/**
  *
读取xml配置文件
  * @param fileName 配置文件名
  */
 private void readXML(String fileName)
 {
  //
寻找配置文件
  URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
  Document doc = null;
  Element root = null;
  try
  {
   SAXBuilder sb = new SAXBuilder(false);
   doc = sb.build(new FileInputStream(new File(xmlPath.toURI())));
   //
设置命名空间   
   Namespace xhtml = Namespace.getNamespace("xhtml",
     "
http://www.springframework.org/schema/beans");
   root = doc.getRootElement(); //
获取根元素   
   List bList = root.getChildren("bean", xhtml); //
获取全部bean节点   
   for (Element beanElement : bList)//
遍历节点,取得每个节点的属性   
   {
    String id = beanElement.getAttributeValue("id");
    String className = beanElement.getAttributeValue("class");
    //
获得每个bean下面的属性
    List pList = beanElement
      .getChildren("property", xhtml);
    List propertyList = new ArrayList(); //
存储属性信息
    if (pList.size() > 0) //如果存在属性
    {
     for (Element propertyElement : pList) //
遍历属性节点
     {
      String name = propertyElement.getAttributeValue("name");
      String ref = propertyElement.getAttributeValue("ref");
      Property property = new Property(name, ref);
      propertyList.add(property); //
保存属性节点
     }
    }
    Bean bean = new Bean(id, className, propertyList);
    beanList.add(bean);
   }

  } catch (Exception e)
  {
   e.printStackTrace();
  }
 }
 
读取完配置文件后我们还是需要对bean进行实例化的,这方法和Spring学习笔记(3)中的instanceBeans()方法一样。下面就是我们需要给bean属性进行注入,实现方法如下:

Java代码 
/**  
     *
bean对象的属性注入值  
     */  
    public void injectObject()   
    {   
        for (Bean bean : beanList)   
        {   
            Object object = beanObject.get(bean.getId()); //
获取bean的实例   
            if (object != null)   
            {   
                try  
                {   
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(   
                            object.getClass()).getPropertyDescriptors();  //
取得bean的属性描述   
                    for (Property property : bean.getPropertyList())  //
获取bean节点的属性   
                    {   
                        for (PropertyDescriptor properdesc : ps)     
                        {   
                            if (property.getName().equals(properdesc.getName()))   
                            {   
                                Method setter = properdesc.getWriteMethod();//
获取属性的setter方法 ,private   
                                if (setter != null)   
                                {   
                                    Object value = beanObject.get(property.getRef());  //
取得值   
                                    setter.setAccessible(true);  //
设置为允许访问   
                                    setter.invoke(object, value);//
把引用对象注入到属性   
                                }   
                                break;   
                            }   
                        }   
                    }   
                } catch (Exception e)   
                {   
                    e.printStackTrace();   
                }   
            }   
        } 

/**
  *
bean对象的属性注入值
  */
 public void injectObject()
 {
  for (Bean bean : beanList)
  {
   Object object = beanObject.get(bean.getId()); //
获取bean的实例
   if (object != null)
   {
    try
    {
     PropertyDescriptor[] ps = Introspector.getBeanInfo(
       object.getClass()).getPropertyDescriptors();  //
取得bean的属性描述
     for (Property property : bean.getPropertyList())  //获取bean节点的属性
     {
      for (PropertyDescriptor properdesc : ps)  
      {
       if (property.getName().equals(properdesc.getName()))
       {
        Method setter = properdesc.getWriteMethod();//
获取属性的setter方法 ,private
        if (setter != null)
        {
         Object value = beanObject.get(property.getRef());  //
取得值
         setter.setAccessible(true);  //设置为允许访问
         setter.invoke(object, value);//把引用对象注入到属性
        }
        break;
       }
      }
     }
    } catch (Exception e)
    {
     e.printStackTrace();
    }
   }
  }

我们进行测试:

Java代码 
MyClassPathXMLApplicationContext ctx=new MyClassPathXMLApplicationContext("applicationContext.xml");     
        UserService service=(UserService)ctx.getBean("userService");   
        service.show(); 

MyClassPathXMLApplicationContext ctx=new MyClassPathXMLApplicationContext("applicationContext.xml");   
  UserService service=(UserService)ctx.getBean("userService");
  service.show();

运行输出

结果代码 
OracleDAO Implement 

OracleDAO Implement 上面仅是简单的演示了Spring依赖注入的原理,但是在实际操作中还需要考虑很对其它因素,在此就不进行讨论了。

 

你可能感兴趣的:(开发框架)