传智播客Spring2.5视频教程_编码剖析Spring依赖注入的原理 3

在传智播客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;
 }
}

因为涉及到 了自省和反射 所以 我讲转载两篇文章。(我感觉,这两种机制 就是为了破坏 封装性, 所谓有一立 就有一破)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值