在Spring學習筆記(3)中剖析了Spring管理Bean的原理,下面解釋下Spring依賴注入的原理
在進行依賴注入時,我們的配置檔案如下配置:
<?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節點的資訊:
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類
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()方法:
/**
* 讀取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屬性進行注入,實作方法如下:
/**
* 為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();
}
}
}
我們進行測試:
MyClassPathXMLApplicationContext ctx=new MyClassPathXMLApplicationContext("applicationContext.xml");
UserService service=(UserService)ctx.getBean("userService");
service.show();
運作輸出
OracleDAO Implement
上面僅是簡單的示範了Spring依賴注入的原理,但是在實際操作中還需要考慮很對其它因素,在此就不進行讨論了。
- spring.rar (2.8 MB)
- 下載下傳次數: 34