三大框架SSH成长路程(二十)

来源:互联网 发布:我是神经病网络歌手 编辑:程序博客网 时间:2024/06/05 08:01

一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)

这篇博文的目标是不仅形似Spring,而且要神似Spring,进一步封装对象的依赖关系。
我们知道Spring框架,不仅可以根据配置创建对象,而且可以根据配置创建对象之间的依赖关系。对象之间的依
赖关系怎么配置呢,那我们先看一下配置文件。

<?xml version="1.0" encoding="UTF-8"?>  <beans>    <bean id="dao" class="com.tgb.container.dao.impl.Dao4MySqlImpl" />    <bean id="service" class="com.tgb.container.service.impl.ServiceImpl">      <property name="dao" ref="dao"></property>    </bean>  </beans>  

我们发现配置文件中多了两个属性:property和ref,表达了Service需要依赖Dao的关系,所以我们需要将dao注入
给Service,怎么做呢?我们只需要像存储bean一样建立一个JavaBean即可:

public class PropertyDefinition {      private String name;      private String ref;      public PropertyDefinition(String name, String ref) {          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;      }  }  

有了javabean,我们就只需要专注于怎么为bean对象的属性注入值。我们可以利用内省来操作Bean类属性、事
件。一般的做法是通过类Introspector来获取某个对象的BeanInfo信息,然后通过BeanInfo来获取属性的描述器
(PropertyDescriptor),通过这个属性描述器就可以获取某个属性对应的getter/setter方法,然后我们就可以通过反
射机制来调用这些方法,最后将引用对象注入到属性中。

import java.beans.Introspector;  import java.beans.PropertyDescriptor;  import java.lang.reflect.Method;  import java.util.ArrayList;  import java.util.HashMap;  import java.util.List;  import java.util.Map;  import org.jdom.Document;  import org.jdom.Element;  import org.jdom.input.SAXBuilder;  import org.jdom.xpath.XPath;  /**  * 容器  *   * @author liang  *   */  public class ClassPathXmlApplicationContext implements BeanFactory {      // 用于存放Bean      private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();      // 用于存放Bean的实例      private Map<String, Object> sigletons =new HashMap<String, Object>();      public ClassPathXmlApplicationContext(String fileName) {          this.readXML(fileName);          this.instanceBeans();          this.injectObject();      }      /**      * 为bean对象的属性注入值      */      private void injectObject() {          for (BeanDefinition beanDefinition :beanDefines) {              Object bean = sigletons.get(beanDefinition.getId());              if(bean != null){                  try {                      // 通过Introspector取得bean的定义信息,之后再取得属性的描述信息,返回一个数组                      PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();                      for(PropertyDefinition propertyDefinition:beanDefinition.getPropertys()){                          for(PropertyDescriptor properdesc: ps){                              if(propertyDefinition.getName().equals(properdesc.getName())){                                  // 获取属性的setter方法,private                                  Method setter = properdesc.getWriteMethod();                                   if(setter != null){                                      Object value = sigletons.get(propertyDefinition.getRef());                                      // 允许访问私有方法                                      setter.setAccessible(true);                                       // 把引用对象注入到属性                                      setter.invoke(bean, value);                                   }                                  break;                              }                          }                      }                  } catch (Exception e) {                      e.printStackTrace();                  }              }          }      }      /**      * 完成bean的实例化      */      private void instanceBeans() {          for(BeanDefinition beanDefinition : beanDefines){              try {                  if(beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())){                      sigletons.put(beanDefinition.getId(),Class.forName(beanDefinition.getClassName()).newInstance() );                  }              } catch (Exception e) {                  e.printStackTrace();              }          }      }      /**      * 读取xml配置文件      */      private void readXML(String fileName) {          // 创建SAXBuilder对象          SAXBuilder saxBuilder = new SAXBuilder();          try {              // 读取资源,获得document对象              Document doc = saxBuilder.build(this.getClass().getClassLoader()                      .getResourceAsStream(fileName));              // 获取根元素              Element rootEle = doc.getRootElement();              // 从根元素获得所有的子元素,建立元素集合              List listBean = XPath.selectNodes(rootEle, "/beans/bean");              // 遍历根元素的子元素集合,扫描配置文件中的bean              for (int i = 0; i < listBean.size(); i++) {                   // 将根元素beans下的bean子元素作为一个新的子根元素                  Element elementBean = (Element) listBean.get(i);                  //获取id属性值                  String id = elementBean.getAttributeValue("id");                  //获取class属性值                  String clazz = elementBean.getAttributeValue("class");                  BeanDefinition beanDefine = new BeanDefinition(id,clazz);                  // 获取子根元素bean下的所有property子元素                  List listProperty = elementBean.getChildren("property");                  // 遍历子根元素的子元素集合(即遍历property元素)                  for (int j = 0; j < listProperty.size(); j++) {                      // 获取property元素                      Element elmentProperty = (Element)listProperty.get(j);                      // 获取name属性值                      String propertyName = elmentProperty.getAttributeValue("name");                      // 获取ref属性值                      String propertyref = elmentProperty.getAttributeValue("ref");                      PropertyDefinition propertyDefinition = new PropertyDefinition(propertyName,propertyref);                      beanDefine.getPropertys().add(propertyDefinition);                  }                  // 将javabean添加到集合中                  beanDefines.add(beanDefine);              }          } catch (Exception e) {              e.printStackTrace();          }      }      /**      * 获取bean实例      */      @Override      public Object getBean(String beanName) {          return this.sigletons.get(beanName);      }  }  

此时我们就可以把Service接口的set方法去掉了。

public interface Service {      public void serviceMethod();  }  

总结

    经过四篇博文的重构,我们实现了一个Spring的雏形,它可以让我们更加深刻的认识Spring的原理,对我们更加 

深入的学习Spring埋下了伏笔。

0 0
原创粉丝点击