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();
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值