spring Ioc 简单实现

来源:互联网 发布:hdmi数字矩阵切换器 编辑:程序博客网 时间:2024/05/01 01:45

地址:http://1011355643.iteye.com/blog/1772840

spring Ioc 简单实现

下面我们来实现一个最简单的Ioc,基本功能是通过SimpleClassPathXmlApplicationContext 获得 beans.xml的2个bean

shoppingDao和shoppingService ,而shoppingService中注入了shoppingDao,它调用了shoppingDao的insert()方法打印出"添加到购物车!"

以下所有代码均经过实例验证通过,复制即可,如果出现问题,100%是jar包缺失导致,请知悉

本人项目结构图

前期准备:

可以新建maven工程,pom.xml添加读取xml文件的依赖包

复制代码
        <dependency>              <groupId>dom4j</groupId>              <artifactId>dom4j</artifactId>              <version>1.6.1</version>        </dependency>        <dependency>            <groupId>jaxen</groupId>            <artifactId>jaxen</artifactId>            <version>1.1-beta-8</version>        </dependency>
复制代码

1.使用junit进行测试,输出“添加到购物车!”

复制代码
public class springIocTest {    @Test    public void test() {        SimpleClassPathXmlApplicationContext sc = new SimpleClassPathXmlApplicationContext(                "beans.xml");        ShoppingService shopping = (ShoppingService) sc                .getBean("shoppingService");        shopping.addToShoppingCart();    }}
复制代码

2.beans.xml文件

复制代码
<?xml version="1.0" encoding="UTF-8"?><beans     xmlns = "http://www.springframework.org/schema/beans"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans                            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  <bean id = "shoppingDao" class= "com.tqt.example.springIoc.ShoppingDaoImpl"></bean><bean id = "shoppingService" class= "com.tqt.example.springIoc.ShoppingServiceImpl">    <property name = "shoppingDao" ref = "shoppingDao"></property></bean></beans>
复制代码

3.基础的ShoppingDao接口和实现方法ShoppingDaoImpl,ShoppingService和ShoppingServiceImpl

复制代码
public interface ShoppingDao {    public void insert();}public class ShoppingDaoImpl implements ShoppingDao {    public void insert() {        //数据库操作,这里只做简单print        System.out.println("添加到购物车!");    }}public interface ShoppingService {    public void addToShoppingCart();}public class ShoppingServiceImpl implements ShoppingService{    //正常情况下使用@Autowire,现在需要get和set方法手动注入    private ShoppingDao shoppingDao;        //调用dao层方法    public void addToShoppingCart() {        getShoppingDao().insert();    }    public ShoppingDao getShoppingDao() {        return shoppingDao;    }    public void setShoppingDao(ShoppingDao shoppingDao) {        this.shoppingDao = shoppingDao;    }}
复制代码

4. pojo类PropertyRef存放bean的名字和引用。BeanDefinition存放id,完整路径的类名,属性

复制代码
/** * @author tqt * 存放属性的对象 */public class PropertyRef {    private String name;    private String ref;        public PropertyRef(String name,String ref)    {        this.name = name;        this.ref = ref;    }    public String getRef() {        return ref;    }    public void setRef(String ref) {        this.ref = ref;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}
复制代码
复制代码
import java.util.ArrayList;import java.util.List;/** * @author tqt 存放xml中的bean的定义 */public class BeanDefinition {    private String id;    private String className;    private List<PropertyRef> propertyRef = new ArrayList<PropertyRef>();    public BeanDefinition(String id, String className) {        this.id = id;        this.className = className;    }    public String getId() {        return id;    }    public void setId(String id) {        this.id = id;    }    public String getClassName() {        return className;    }    public void setClassName(String className) {        this.className = className;    }    public List<PropertyRef> getPropertyRef() {        return propertyRef;    }    public void setPropertyRef(List<PropertyRef> propertyRef) {        this.propertyRef = propertyRef;    }}
复制代码

5.核心容器

复制代码
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;/** * @author tqt 简易springIoc容器 */public class SimpleClassPathXmlApplicationContext {    // 存放bean的id、类名、属性list对象    private static List<BeanDefinition> beanDefinitionList = new ArrayList<BeanDefinition>();    // 存放id和对应的class实例    private static Map<String, Object> pojos = new HashMap<String, Object>();    /**     * @param fileName     */    public SimpleClassPathXmlApplicationContext(String fileName) {        this.readXml(fileName);        this.instanceBeans();        this.injectObject();    }    /**     * 简单读取xml文件     * 需要dom4j,dom4j需要jaxen     * @param fileName     */    private void readXml(String fileName) {        String id = null;        String clazz = null;        String propertyName = null;        String propertyRefNode = null;        BeanDefinition beanDefine = null;        PropertyRef propertyRef = null;        List<Element> properties = new ArrayList<Element>();                Map<String, String> nameSpaceMap = new HashMap<String, String>();        SAXReader saxReader = new SAXReader();        URL filePath = this.getClass().getClassLoader().getResource(fileName);        try {            // dom4j Document读取文档            Document doc = saxReader.read(filePath);            // 加入命名空间            nameSpaceMap.put("nameSpace", "http://www.springframework.org/schema/beans");            // dom4j xpath创建beans/bean查询路径            XPath xpath = doc.createXPath("nameSpace:beans/nameSpace:bean");            // 设置命名空间            xpath.setNamespaceURIs(nameSpaceMap);            // 获取文档下所有bean节点            List<Element> beans = xpath.selectNodes(doc);            for (Element element : beans) {                // 获取id属性值                id = element.attributeValue("id");                // 获取class属性值                clazz = element.attributeValue("class");                // 本地bean的对象                beanDefine = new BeanDefinition(id, clazz);                // 获得所有的属性                List<PropertyRef> propertyRefs = new ArrayList<PropertyRef>();                XPath propertiesX = element.createXPath("nameSpace:property");                propertiesX.setNamespaceURIs(nameSpaceMap);                properties = propertiesX.selectNodes(element);                for (Element property : properties) {                    propertyName = property.attributeValue("name");                    propertyRefNode = property.attributeValue("ref");                    propertyRef = new PropertyRef(propertyName, propertyRefNode);                    propertyRefs.add(propertyRef);                }                // 设置所有属性                beanDefine.setPropertyRef(propertyRefs);                // 添加属性到bean变量                beanDefinitionList.add(beanDefine);            }        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 实例化bean     */    private void instanceBeans() {        for (BeanDefinition beanDefinition : beanDefinitionList) {            if (null != beanDefinition.getClassName()                    || "".equals(beanDefinition.getClassName().trim())) {                try {                    pojos.put(beanDefinition.getId(),                            Class.forName(beanDefinition.getClassName())                                    .newInstance());                } catch (Exception e) {                    e.printStackTrace();                }            }        }    }    /**     * 注入属性     */    private void injectObject() {        for (BeanDefinition beanDefinition : beanDefinitionList) {            Object bean = pojos.get(beanDefinition.getId());            if (null != bean) {                PropertyDescriptor[] pdArray;                try {                    // 使用拦截器获得指定的bean的所有属性                    pdArray = Introspector.getBeanInfo(bean.getClass())                            .getPropertyDescriptors();                    for (PropertyRef pr : beanDefinition.getPropertyRef()) {                        for (PropertyDescriptor pd : pdArray) {                            // 如果找到该属性就获得setter方法并赋值                            if (pr.getName().equals(pd.getName())) {                                // 获取属性的setter方法                                Method setter = pd.getWriteMethod();                                if (null != setter) {                                    Object ob = pojos.get(pr.getRef());                                    // 访问权限设置                                    setter.setAccessible(true);                                    // 把引用对象注入到属性                                    setter.invoke(bean, ob);                                }                            }                        }                    }                } catch (Exception e) {                    e.printStackTrace();                }            }        }    }    /**     * 获得bean实例     *      * @param beanName     * @return     */    public Object getBean(String beanName) {        return this.pojos.get(beanName);    }}