spring依赖注入原理

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

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

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


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

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

Xml代码
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="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/beans http://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 id="mySqlDAO" class="com.szy.spring.dao.UserDAO4MySqlImpl"/> 
    <bean id="oracleDAO" class="com.szy.spring.dao.UserDAO4OracleImpl"/> 
    <bean id="userService" class="com.szy.spring.service.UserServiceImpl"> 
        <!--构造方法注入    
            <property name="userDAO" ref="mySqlDAO"></property> 
        --> 
        <property name="userDAO" ref="oracleDAO"></property> 
    </bean> 
</beans> 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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/beans http://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 id="mySqlDAO" class="com.szy.spring.dao.UserDAO4MySqlImpl"/>
 <bean id="oracleDAO" class="com.szy.spring.dao.UserDAO4OracleImpl"/>
 <bean id="userService" class="com.szy.spring.service.UserServiceImpl">
  <!--构造方法注入 
   <property name="userDAO" ref="mySqlDAO"></property>
  -->
  <property name="userDAO" ref="oracleDAO"></property>
 </bean>
</beans>
 根据配置文件信息,我们首先需要建立一个Bean类,用来保存bean节点的信息:

Java代码
package com.szy.spring.bean;  
 
import java.util.List;  
 
public class Bean  
{  
    private String id;     
    private String className;   
    private List<Property> propertyList;  
    public Bean(String id, String className, List<Property> 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<Property> getPropertyList()  
    {  
        return propertyList;  
    }  
    public void setPropertyList(List<Property> propertyList)  
    {  
        this.propertyList = propertyList;  
    }     

package com.szy.spring.bean;

import java.util.List;

public class Bean
{
 private String id;  
    private String className;
    private List<Property> propertyList;
 public Bean(String id, String className, List<Property> 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<Property> getPropertyList()
 {
  return propertyList;
 }
 public void setPropertyList(List<Property> 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<Element> bList = root.getChildren("bean", xhtml); //获取全部bean节点     
            for (Element beanElement : bList)// 遍历节点,取得每个节点的属性     
            {  
                String id = beanElement.getAttributeValue("id");  
                String className = beanElement.getAttributeValue("class");  
                //获得每个bean下面的属性  
                List<Element> pList = beanElement  
                        .getChildren("property", xhtml);  
                List<Property> propertyList = new ArrayList<Property>(); //存储属性信息  
                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<Element> bList = root.getChildren("bean", xhtml); //获取全部bean节点  
   for (Element beanElement : bList)// 遍历节点,取得每个节点的属性  
   {
    String id = beanElement.getAttributeValue("id");
    String className = beanElement.getAttributeValue("class");
    //获得每个bean下面的属性
    List<Element> pList = beanElement
      .getChildren("property", xhtml);
    List<Property> propertyList = new ArrayList<Property>(); //存储属性信息
    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依赖注入的原理,但是在实际操作中还需要考虑很对其它因素,在此就不进行讨论了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值