Spring2.5 IOC的简单实现
1、定义一个接口
package com.css.framework.context;public interface MyApplicationContext {/** * 获取bean的实例 * @param beanName * @return */public Object getBean(String beanName);}
??2、Bean节点的描述文件
package com.css.framework.beans.factory.config;import java.util.ArrayList;import java.util.List;/** * Spring Bean 的描述文件 * * @author Administrator * */public class BeanDefinition { //Bean节点中的id属性private String id;//Bean节点中的className属性private String className;/** * Bean节点中的属性描述property节点 */private List<PropertyDefinition> properties = new ArrayList<PropertyDefinition>();public String getId() {return id;}public BeanDefinition(String id, String className) {super();this.id = id;this.className = className;}public void setId(String id) {this.id = id;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;} public List<PropertyDefinition> getProperties() { return properties; } public void setProperties(List<PropertyDefinition> properties) { this.properties = properties; }}
?
package com.css.framework.beans.factory.config;/**** <p>Title: property节点的描述文件 </p>* <p>Description: property节点的描述文件</p>* <p>Copyright: Copyright (c) 2010,CSS</p>* <p>Company: CSS</p>* @author 章殷* @date 2010-6-19* @version 1.0*/public class PropertyDefinition { private String name; private String ref; private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public PropertyDefinition(String name, String ref,String value) { super(); this.name = name; this.ref = ref; this.value = value; } 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; }}
?
4、关键的实现类
package com.css.framework.context;import java.beans.IntrospectionException;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;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.apache.commons.beanutils.ConvertUtils;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.XPath;import org.dom4j.io.SAXReader;import com.css.framework.annotation.MyResource;import com.css.framework.beans.factory.config.BeanDefinition;import com.css.framework.beans.factory.config.PropertyDefinition;import com.css.inter.IConstructorServiceBean;/**** <p>Title: 加载beans.xml文件 </p>* <p>Description: 加载xml文件,实例化文件中的Bean,并实现IOC</p>* <p>Copyright: Copyright (c) 2010,CSS</p>* <p>Company: CSS</p>* @author 章殷* @date 2010-6-19* @version 1.0*/public class MyClassPathXmlApplicationContext implements MyApplicationContext { //所有的bean的描述文件列表 private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>(); //定义所有的实例化的Bean private Map<String, Object> sigletons = new HashMap<String, Object>(); public MyClassPathXmlApplicationContext(String filename) { //加载配置文件 readXml(filename); //实例化配置文件中的Bean instanceBeans(); //使用注解方法进行注入 annotationInject(); //给Bean注入对象 injectObject(); } /** * <p> 使用注解的方式,将对象注入到实例Bean中。</p> * @author 章 殷 * @date 2010-6-19 */ private void annotationInject() { //循环所有实例化的Bean for (String beanName : sigletons.keySet()) { //获取Bean Object bean = sigletons.get(beanName); if (bean != null) { try { //通过属性注入 propertyInject(bean); //通过字段注入,包括字段的名称 fieldInject(bean); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * <p> 通过属性名属性类型进行注入。</p> * @param bean * @throws IntrospectionException * @throws IllegalAccessException * @throws InvocationTargetException * @author 章 殷 * @date 2010-6-19 */ private void propertyInject(Object bean) throws IntrospectionException, IllegalAccessException, InvocationTargetException { //获取Bean的属性描述信息,通过setter方法进行注入 PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for (PropertyDescriptor propertyDesc : ps) { //获取属性的setter方法 Method setter = propertyDesc.getWriteMethod(); //判断setter方法是否存储,时候存在MyResource注解 if (setter != null && setter.isAnnotationPresent(MyResource.class)) { //获取属性的注解 MyResource resource = setter.getAnnotation(MyResource.class); Object value = null; //判断注解的name值是否为空,是否为空字符 if (resource.name() != null && !"".equals(resource.name())) { //从容器中取出name对应的对象 value = sigletons.get(resource.name()); } //下面的方法是通过属性名和属性的类型来查找实例Bean else { //通过属性名来查找对应的实体Bean value = sigletons.get(propertyDesc.getName()); if (value == null) { //通过属性的类型来查找对应的实体Bean for (String key : sigletons.keySet()) { // 循环所有的容器Bean,判断属性的类型和容器中的类型是否匹配 if (propertyDesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())) { value = sigletons.get(key); break; } } } } setter.setAccessible(true);//如果是私有的方法,设置该值为true,就可以调用该setter方法 setter.invoke(bean, value); //把引用注入到Bean中 } } } /** * <p> 通过字段名进行实例注入。</p> * @param bean * @throws IllegalAccessException * @author 章 殷 * @date 2010-6-19 */ private void fieldInject(Object bean) throws IllegalAccessException { //获取Bean的所有字段信息 Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { //判断字段上是否存在MyResource注解 if (field.isAnnotationPresent(MyResource.class)) { MyResource resource = field.getAnnotation(MyResource.class); Object value = null; //通过注解的Name属性来查询实体Bean if (resource.name() != null && !"".equals(resource.name())) { value = sigletons.get(resource.name()); } //通过字段的名称和字段类型来查询实例Bean else { value = sigletons.get(field.getName());//通过属性名来查找 if (value == null) { for (String key : sigletons.keySet()) { if (field.getType().isAssignableFrom(sigletons.get(key).getClass())) { value = sigletons.get(key); break; } } } } field.setAccessible(true);//设置私有的属性可以进行访问 field.set(bean, value); //将应用注入到属性中 } } } /** * <p> IOC的Spring的实现,该方法是用的是属性注入,可以注入依赖对象和基本数据类型。</p> * @author 章 殷 * @date 2010-6-18 */ private void injectObject() { System.out.println("============开始进行IOC注入=============="); //循环所有的beanDefines for (BeanDefinition beanDefinition : beanDefines) { //获取实例化后的bean Object bean = sigletons.get(beanDefinition.getId()); if (bean != null) { //获取实例化后的Bean的属性描述西西里 try { PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for (PropertyDefinition propertyDefinition : beanDefinition.getProperties()) { for (PropertyDescriptor propertyDescriptor : ps) { Method setter = null; //判断Bean的属性名 与 property节点中的Name值是否相同 if (propertyDefinition.getName().equals(propertyDescriptor.getName())) { setter = propertyDescriptor.getWriteMethod();//获取实例化Bean的set方法 if (setter != null) { Object value = null; //如果引用存在,注入依赖对象 if (propertyDefinition.getRef() != null && !"".equals(propertyDefinition.getRef().trim())) { value = sigletons.get(propertyDefinition.getRef());//从容器中获取ref的Bean } //注入基本数据类型 else { value = ConvertUtils.convert(propertyDefinition.getValue(), propertyDescriptor .getPropertyType()); } setter.setAccessible(true);//如果是私有的方法,设置该值为true,就可以调用该setter方法 setter.invoke(bean, value); //把引用注入到Bean中 System.out.println("注入[" + beanDefinition.getClassName() + "]的" + propertyDefinition.getName() + "属性成功"); } } } } } catch (Exception e) { System.err.println("注入【" + beanDefinition.getClassName() + "】时出错!"); } } } System.out.println("============IOC注入完成=============="); System.out.println(""); } /** * <p> 实例化beanDefines中的所有Bean。</p> * @author 章 殷 * @date 2010-6-18 */ private void instanceBeans() { System.out.println("============开始实例化Bean=============="); for (BeanDefinition beanDefinition : beanDefines) { try { if (beanDefinition.getClassName() != null && !"".equals(beanDefinition.getClassName().trim())) { sigletons.put(beanDefinition.getId(), Class.forName(beanDefinition.getClassName()).newInstance()); System.out.println("实例化[" + beanDefinition.getClassName() + "]成功!"); } } catch (Exception e) { System.err.println("实例化[" + beanDefinition.getClassName() + "]时出错!"); e.printStackTrace(); } } System.out.println("============实例化Bean完成=============="); System.out.println(""); } /** * <p> 读取bean.xml文件,将xml的描述文件转换为java描述文件。</p> * @param filename * @author 章 殷 * @date 2010-6-18 */ @SuppressWarnings("unchecked") private void readXml(String filename) { System.out.println("============开始加载配置文件" + filename + "=============="); SAXReader saxReader = new SAXReader(); Document document = null; URL xmlpath = this.getClass().getClassLoader().getResource(filename); try { document = saxReader.read(xmlpath); Map<String, String> nsMap = new HashMap<String, String>(); nsMap.put("ns", "http://www.springframework.org/schema/beans"); //定位到beans/bean节点下 XPath xsub = document.createXPath("//ns:beans//ns:bean"); xsub.setNamespaceURIs(nsMap); //设置命名空间 List<Element> beans = xsub.selectNodes(document); //获取xml中所有的bean节点 for (Element element : beans) { String id = element.attributeValue("id"); //获取属性id的值 String clazz = element.attributeValue("class");//获取属性class的值 BeanDefinition beanDefinition = new BeanDefinition(id, clazz); //将Bean.xml文件中的property节点映射到beanDefinition XPath propertySub = element.createXPath("ns:property"); //创建property的相对路径 propertySub.setNamespaceURIs(nsMap); List<Element> propertis = propertySub.selectNodes(element); for (Element property : propertis) { String propertyName = property.attributeValue("name"); String propertyRef = property.attributeValue("ref"); String propertyValue = property.attributeValue("value"); beanDefinition.getProperties().add( (new PropertyDefinition(propertyName, propertyRef, propertyValue))); System.out.println(">>>>:加载属性[" + clazz + ".(" + propertyRef + ")]成功!"); } beanDefines.add(beanDefinition); System.out.println(">>>>:加载类[" + clazz + "]成功!"); } } catch (DocumentException e) { System.err.println("加载配置文件<" + xmlpath + ">时出错!"); e.printStackTrace(); } System.out.println("============配置文件" + filename + "加载完成=============="); System.out.println(""); } /** * 获取bean的实例 * @param beanName * @return */ public Object getBean(String beanName) { return sigletons.get(beanName); } public static void main(String[] args) { MyApplicationContext context = new MyClassPathXmlApplicationContext("beans.xml"); // IPersonServiceBean personService = (IPersonServiceBean) context.getBean("personService"); // personService.save(); IConstructorServiceBean constructor = (IConstructorServiceBean) context.getBean("constructorServiceBean"); constructor.save(); }}
?