您的位置:首页 > 编程语言 > Java开发

Spring框架的IOC/DI的自己实现

2016-11-15 19:58 423 查看
   今天咱们就一起探索spring是怎么完成IOC/DI工作的,也自己做一个简单Spring框架!


Spring中Bean的定义

作用:在spring中使用的bean,都有某些公共属性,此类就是对公共属性的定义

[java] view
plain copy

 print?





public class BeanDefine {    

    

    public String id;    

    public String className;    

    

    public BeanDefine(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;    

    }    

    

}  


2,装配类

2.1,XML装配类

作用:对spring中Xml的配置进行类的装配,实际就是注入

[java] view
plain copy

 print?





import java.beans.Introspector;    

import java.beans.PropertyDescriptor;    

import java.lang.reflect.Field;    

import java.lang.reflect.Method;    

import java.util.ArrayList;    

import java.util.HashMap;    

import java.util.Iterator;    

import java.util.List;    

import java.util.Map;    

import org.apache.log4j.Logger;    

import org.dom4j.Document;    

import org.dom4j.DocumentException;    

import org.dom4j.Element;    

import org.dom4j.io.SAXReader;    

    

import com.My.Test.TestServiceImpl;    

    

/**  

 * @Description: spring中的注解原理  

 * @ClassName: ClassPathXMLApplicationContext  

 * @Project: MySpring  

 * @Author: xvshu  

 * @Date: 2015年2月28日  

 */    

public class ClassPathXMLApplicationContext {    

    

    Logger log = Logger.getLogger(ClassPathXMLApplicationContext.class);    

    

    List<BeanDefine> beanList = new ArrayList<BeanDefine>();    

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

    

    public ClassPathXMLApplicationContext(String fileName) {    

        //读取配置文件中管理的bean    

        this.readXML(fileName);    

        //实例化bean    

        this.instancesBean();    

        //注解处理器    

        this.annotationInject();    

    }    

    

    /**  

     * 读取Bean配置文件  

     * @param fileName  

     * @return  

     */    

    @SuppressWarnings("unchecked")    

    public void readXML(String fileName) {    

        Document document = null;    

        SAXReader saxReader = new SAXReader();    

        try {    

            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();    

            document = saxReader.read(classLoader.getResourceAsStream(fileName));    

            Element beans = document.getRootElement();    

            for (Iterator<Element> beansList = beans.elementIterator(); beansList.hasNext();) {    

                Element element = beansList.next();    

                BeanDefine bean = new BeanDefine(    

                        element.attributeValue("id"),    

                        element.attributeValue("class"));    

                beanList.add(bean);    

            }    

        } catch (DocumentException e) {    

            log.info("读取配置文件出错....");    

        }    

    }    

        

    /**  

     * 实例化Bean  

     */    

    public void instancesBean() {    

        for (BeanDefine bean : beanList) {    

            try {    

                sigletions.put(bean.getId(), Class.forName(bean.getClassName()).newInstance());    

            } catch (Exception e) {    

                log.info("实例化Bean出错...");    

            }    

        }    

    }    

        

    /**  

     * 注解处理器  

     * 如果注解ZxfResource配置了name属性,则根据name所指定的名称获取要注入的实例引用,如果注解ZxfResource  

     * 没有配置name属性,则根据属性所属类型来扫描配置文件获取要注入的实例引用  

     *   

     */    

    public void annotationInject(){    

        for(String beanName:sigletions.keySet()){    

            Object bean = sigletions.get(beanName);    

            if(bean!=null){    

                this.propertyAnnotation(bean);    

                this.fieldAnnotation(bean);    

            }    

        }    

    }    

        

    /**  

     * 处理在set方法加入的注解  

     * @param bean 处理的bean  

     */    

    public void propertyAnnotation(Object bean){    

        try {    

            //获取其属性的描述    

            PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();    

            for(PropertyDescriptor proderdesc : ps){    

                //获取所有set方法    

                Method setter = proderdesc.getWriteMethod();    

                //判断set方法是否定义了注解    

                if(setter!=null && setter.isAnnotationPresent(ZxfResource.class)){    

                    //获取当前注解,并判断name属性是否为空    

                    ZxfResource resource = setter.getAnnotation(ZxfResource.class);    

                    String name ="";    

                    Object value = null;    

                    if(resource.name()!=null&&!"".equals(resource.name())){    

                        //获取注解的name属性的内容    

                        name = resource.name();    

                        value = sigletions.get(name);    

                    }else{ //如果当前注解没有指定name属性,则根据类型进行匹配    

                        for(String key : sigletions.keySet()){    

                            //判断当前属性所属的类型是否在配置文件中存在    

                            if(proderdesc.getPropertyType().isAssignableFrom(sigletions.get(key).getClass())){    

                                //获取类型匹配的实例对象    

                                value = sigletions.get(key);    

                                break;    

                            }    

                        }    

                    }    

                    //允许访问private方法    

                    setter.setAccessible(true);    

                    //把引用对象注入属性    

                    setter.invoke(bean, value);     

                }    

            }    

        } catch (Exception e) {    

            log.info("set方法注解解析异常..........");    

        }    

    }    

        

    /**  

     * 处理在字段上的注解  

     * @param bean 处理的bean  

     */    

    public void fieldAnnotation(Object bean){    

        try {    

            //获取其全部的字段描述    

            Field[] fields = bean.getClass().getDeclaredFields();    

            for(Field f : fields){    

                if(f!=null && f.isAnnotationPresent(ZxfResource.class)){    

                    ZxfResource resource = f.getAnnotation(ZxfResource.class);    

                    String name ="";    

                    Object value = null;    

                    if(resource.name()!=null&&!"".equals(resource.name())){    

                        name = resource.name();    

                        value = sigletions.get(name);    

                    }else{    

                        for(String key : sigletions.keySet()){    

                            //判断当前属性所属的类型是否在配置文件中存在    

                            if(f.getType().isAssignableFrom(sigletions.get(key).getClass())){    

                                //获取类型匹配的实例对象    

                                value = sigletions.get(key);    

                                break;    

                            }    

                        }    

                    }    

                    //允许访问private字段    

                    f.setAccessible(true);    

                    //把引用对象注入属性    

                    f.set(bean, value);    

                }    

            }    

        } catch (Exception e) {    

            log.info("字段注解解析异常..........");    

        }    

    }    

        

    /**  

     * 获取Map中的对应的bean实例  

     * @param beanId  

     * @return  

     */    

    public Object getBean(String beanId) {    

        return sigletions.get(beanId);    

    }    

    

    

}    

2.2,注解装配类

作用:对spring中用注解标记的部分进行注入,就是一个自定义注解

[java] view
plain copy

 print?





import java.lang.annotation.ElementType;    

import java.lang.annotation.Retention;    

import java.lang.annotation.RetentionPolicy;    

import java.lang.annotation.Target;    

     

// 在运行时执行    

@Retention(RetentionPolicy.RUNTIME)    

// 注解适用地方(字段和方法)    

@Target({ ElementType.FIELD, ElementType.METHOD })    

public @interface ZxfResource {    

    

    //注解的name属性    

    public String name() default "";    

}    

3,配置文件

3.1xml:

[javascript] view
plain copy

 print?





<?xml version="1.0" encodi  

<beans>      

    <bean id = "TestObject1" class="com.My.Test.TestObject1" />      

    <bean id = "TestObject2" class="com.My.Test.TestObject2" />      

    <bean id = "TestObject3" class="com.My.Test.TestObject3" />      

    <bean id = "TestService" class = "com.My.Test.TestServiceImpl" />      

</beans>   

3.2注解

[java] view
plain copy

 print?





public class TestServiceImpl {    

    

    public TestObject3 TestObject3;    

    public TestObject1 TestObject1;    

    

    // 字段上的注解,可以配置name属性    

    @ZxfResource    

    public TestObject2 TestObject2;    

    

    // set方法上的注解,带有name属性    

    @ZxfResource(name = "TestObject3")    

    public void setUserDao(TestObject3 TestObject3) {    

        this.TestObject3 = TestObject3;    

    }    

    

    // set方法上的注解,没有配置name属性    

    @ZxfResource    

    public void setUser1Dao(TestObject1 TestObject1) {    

        this.TestObject1 = TestObject1;    

    }    

    

    public void show() {    

            

        TestObject1.show1();    

        TestObject2.show2();    

        TestObject3.show();    

            

        System.out.println("调用了TestService方法........");    

            

    }    

}    



4,测试类

和普通spring类一样的写法

[java] view
plain copy

 print?





public static void main(String[] args) {    

        ClassPathXMLApplicationContext path = new ClassPathXMLApplicationContext(    

                "configAnnotation.xml");    

        TestServiceImpl userService =(TestServiceImpl)path.getBean("TestService");    

        userService.show();    

}  

5,原文博客地址

http://blog.csdn.net/xvshu/article/details/43981973

6,源码下载

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring 框架 IOC DI