使用构造器注入
使用属性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/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">
<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/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 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依赖注入的原理,但是在实际操作中还需要考虑很对其它因素,在此就不进行讨论了。