用JDom与反射机制打造自己的小型Spring容器

本文介绍了一个基于Spring框架的自定义实现——ClassPathXMLApplicationContext类。该类能够读取XML配置文件,解析并实例化Bean,同时完成依赖注入。通过反射机制调用setter方法实现属性注入。

核心代码 :

 

 

package org.rejoy.spring;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
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.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
import org.rejoy.spring.bean.BeanDefinition;
import org.rejoy.spring.bean.PropertyDefinition;

public class ClassPathXMLApplicationContext {
 private List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();

 private Map<String, Object> beanMap = new HashMap<String, Object>();

 public ClassPathXMLApplicationContext(String fileName) {
  this.readXML(fileName);
  this.instanceBeans();
  this.injectObject();
 }

 private void injectObject() {
  for (BeanDefinition beanDefinition : beanDefinitions) {
   Object bean = beanMap.get(beanDefinition.getId());
   if (bean != null) {
    try {
     PropertyDescriptor[] ps = Introspector.getBeanInfo(
       bean.getClass()).getPropertyDescriptors();
     for (PropertyDefinition propertyDefinition : beanDefinition
       .getProperties()) {
      for (PropertyDescriptor properdesc : ps) {
       if (propertyDefinition.getName().equals(
         properdesc.getName())) {
        Method setter = properdesc.getWriteMethod();// 获取属性的setter方法
        if (setter != null) {
         Object value = beanMap
           .get(propertyDefinition.getRef());
         setter.setAccessible(true);
         setter.invoke(bean, value);// 把引用对象注入到属性
        }
        break;
       }
      }
     }
    } catch (Exception e) {
    }
   }
  }
 }

 private void instanceBeans() {
  for (BeanDefinition beanDefinition : beanDefinitions) {
   try {
    if (beanDefinition.getClassName() != null
      && !"".equals(beanDefinition.getClassName()))
     beanMap.put(beanDefinition.getId(), Class.forName(
       beanDefinition.getClassName()).newInstance());
   } catch (InstantiationException e) {
    e.printStackTrace();
   } catch (IllegalAccessException e) {
    e.printStackTrace();
   } catch (ClassNotFoundException e) {
    e.printStackTrace();
   }
  }
 }

 @SuppressWarnings("unchecked")
 private void readXML(String fileName) {
  SAXBuilder saxBuilder = new SAXBuilder();
  try {
   Document document = saxBuilder.build(this.getClass()
     .getClassLoader().getResourceAsStream(fileName));
   Element root = document.getRootElement();
   List<Element> list = XPath.selectNodes(root, "//beans/bean");
   for (Element element : list) {
    String id = element.getAttributeValue("id");
    String clazz = element.getAttributeValue("class");
    BeanDefinition beanDefinition = new BeanDefinition(id, clazz);
    List<Element> properties = XPath.selectNodes(root,
      "//beans/bean/property");
 
    for (Element property : properties) {
     String propertyName = property.getAttributeValue("name");
     String propertyRef = property.getAttributeValue("ref");
     PropertyDefinition propertyDefinition = new PropertyDefinition(
       propertyName, propertyRef);
     beanDefinition.getProperties().add(propertyDefinition);
    }
    beanDefinitions.add(beanDefinition);
   }
  } catch (JDOMException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }

 public Object getBean(String beanName) {
  return beanMap.get(beanName);
 }
}
 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值