在传智播客Spring2.5视频教程_编码剖析Spring依赖注入的原理1 的基础上 实现注入功能:
绿色字体部分,
package six.spring.application;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;
import six.spring.application.beandefinition.BeanDefinition;
import six.spring.application.beandefinition.PropertyBeanDefinition;
public class ClassPathXMLApplicationContext {
private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
private Map<String, Object> objsMap = new HashMap<String, Object>();
public ClassPathXMLApplicationContext(String fileName)
throws ClassNotFoundException {
this.readXML(fileName);
this.instanceBeans();
this.injectObject();
}
// 实现注入功能
private void injectObject() {
for (BeanDefinition beanDefinition : beanDefinitions) {
// 将 已经实例化的对象 迭代
Object bean = objsMap.get(beanDefinition.getId());
// 要养成 对 对象判空的编码习惯
if (null != bean){
try {
//利用自反省机制获取成员变量, 继而获得对应的get set 方法
PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
for (PropertyBeanDefinition myPropertyBeanDefinition : beanDefinition.getPropertys()) {
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getName().equals(myPropertyBeanDefinition.getName()) ){
// 通过调用set方法 注入
Method method = propertyDescriptor.getWriteMethod();
// 要养成 对 对象判空的编码习惯
if (null != method) {
Object value = objsMap.get(myPropertyBeanDefinition.getHref());
// 要养成 对 对象判空的编码习惯
if (value != null){
method.setAccessible(true);
method.invoke(bean, value);
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void instanceBeans()
}
private void readXML(String fileName) {
SAXReader saxReader = new SAXReader();
Document document = null;
try {
URL xmlPath = this.getClass().getClassLoader().getResource(fileName);
document = saxReader.read(xmlPath);
Map<String, String> nsMap = new HashMap<String, String>();
// 加入命名空间
nsMap.put("ns", "http://www.springframework.org/schema/beans");
// 创建beans/bean查询路径
XPath xPath = document.createXPath("//ns:beans/ns:bean");
// 设置命名空间
xPath.setNamespaceURIs(nsMap);
//取得根元素下的所有节点
List<Element> beans = xPath.selectNodes(document);
for (Element element : beans) {
String id = element.attributeValue("id");
String clazz = element.attributeValue("class");
BeanDefinition beanDefinition = new BeanDefinition(id, clazz);
// 不需要 带根路径
XPath xPathBeanDefinition = element.createXPath("ns:property");
// 设置命名空间
xPathBeanDefinition.setNamespaceURIs(nsMap);
//取得[Element]元素下的所有 节点
List<Element> propertyBeans = xPathBeanDefinition.selectNodes(element);
for (Element propertyBean : propertyBeans) {
String name = propertyBean.attributeValue("name");
String ref = propertyBean.attributeValue("ref");
PropertyBeanDefinition propertyDefination = new PropertyBeanDefinition(name, ref);
beanDefinition.getPropertys().add(propertyDefination);
}
beanDefinitions.add(beanDefinition);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public List<BeanDefinition> getBeanDefinitions() {
return beanDefinitions;
}
public void setBeanDefinitions(List<BeanDefinition> beanDefinitions) {
this.beanDefinitions = beanDefinitions;
}
public Map<String, Object> getObjsMap() {
return objsMap;
}
public void setObjsMap(Map<String, Object> objsMap) {
this.objsMap = objsMap;
}
}
因为涉及到 了自省和反射 所以 我讲转载两篇文章。(我感觉,这两种机制 就是为了破坏 封装性, 所谓有一立 就有一破)