spring原理的简单实现(01)

描述:spring的两大核心是ioc和aop,这里我简单的实现下ioc,即控制反转。ioc的具体解释这里不做说明,首先spring的ioc解决的核心问题就是帮助我们抛去了传统的再依赖的代码调用中new的一种形式。


1  springioc最初使用的是xml的结构化配置,也就是把实体之前的依赖关系抽离出来,在xml中进行配置,然后spring帮助我们构建这层依赖关系,并把构建的这些关系以及实例放入spring的容器中,这样我们就可以通过spring的容器去拿到我们想要的对象。

2  因为jdk1.5以后就支持了注解形式,同时spring也支持注解的模式,就是已注解的形式替代xml的配置关系。其原理都是一样的。

这里我们仅仅模拟xml读取后,对bean标签中各依赖,或者属性的注入,然后去获取想要的实例bean

首先,spring中可以有多种形式来获取到spring的xml配置文件并初始化容器 

1.  XmlBeanFactory    工厂bean的形式获取

    Resource cr = new ClassPathResource("applicationContext.xml");

    BeanFactory bf=new XmlBeanFactory(cr);

    UserDao userDao = (UserDao)bf.getBean("userDao");

2  ClassPathXmlApplicationContext  

使用ClassPathXmlApplicationContext对象获取,必须把applicationContext.xml放置到类的加载路径【classpath路径下】中,也就是Src下面

1.ApplicationContext factory=new ClassPathXmlApplicationContext("classpath:appcontext.xml");

factory.getBean();

3 FileSystemXmlApplicationContext

   使用文件的系统路径,可以是本地的任何位置

4 XmlWebApplicationContext

   在web项目中根据web.xml中配置的xml路径进行读取

------------------------------------------------------------

这里我们自己实现一个BeanFactory实现如下简单功能

1  读取xml

2 解析xml

3 反射获取

4 反射注入


具体代码如下

package test.spring;

import com.sun.xml.internal.bind.v2.runtime.output.NamespaceContextImpl;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class BeanFactory {

    public static Map<String,Object> contain = null;

    public void init(String xml) throws DocumentException, IllegalAccessException, InstantiationException, ClassNotFoundException, IntrospectionException, InvocationTargetException {
        contain = new HashMap<String,Object>();
        SAXReader reader = new SAXReader();
        // 从class目录下获取指定的xml文件
        InputStream ins = BeanFactory.class.getResourceAsStream(xml);
        Document doc = reader.read(ins);
        Element root = doc.getRootElement();
        System.out.println(root.getName());
        Element foo;
        // 遍历bean
        Iterator<Element> iterator = root.elementIterator("bean");  //获取所有bean标签集合
        while(iterator.hasNext()){
            Element bean = iterator.next();
            Attribute key = bean.attribute("id");
            if("".equals(key.getText())){
                throw new NullPointerException();
            }
            Attribute clazzName = bean.attribute("class");
            if("".equals(clazzName.getText())){
                throw new NullPointerException();
            }


            Object obj = classFor(clazzName.getText());
            Iterator<Element> propertys = bean.elementIterator("property");
            while(propertys.hasNext()){
                Element property = propertys.next();
                Attribute name = property.attribute("name");
                Attribute value = property.attribute("value");
                if(value!=null){
                    setProperty(obj,name.getText(),value.getValue());
                }
                Attribute ref = property.attribute("ref");
                if(ref != null){
                   Object nObj =  contain.get(ref.getText());
                   if(nObj != null){
                       setProperty(obj,name.getText(),nObj);
                   }
                }
            }
            contain.put(key.getText(), obj);
        }
    }


    public <T> T getBean(String beanName){
        return (T)contain.get(beanName);
    }

    public <T> T classFor(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class c = Class.forName(className);
        T t = (T)c.newInstance();
        return t;
    }

    /***
     * 通过class的getMethod方法可以获取到指定的方法对象,
     * @param clazz
     * @return
     * @throws IntrospectionException
     */
    private BeanInfo getBeanInfo(Class clazz) throws IntrospectionException {
        return Introspector.getBeanInfo(clazz);
    }

    private void setProperty(Object o,String propertyName,Object val) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        BeanInfo bi = getBeanInfo(o.getClass());
        PropertyDescriptor[] propertyDescriptors = bi.getPropertyDescriptors();
        if(propertyDescriptors != null && propertyDescriptors.length>0){
            for (PropertyDescriptor pd : propertyDescriptors){
                if(pd.getName().equals(propertyName)){
                    Object type = pd.getPropertyType();  //当前属性的类型
                    Method method = pd.getWriteMethod();   //获取当前属性对应的set方法
                    method.invoke(o,val);
                    break;
                }
            }
        }
    }

    private Object getPropertyValByBeanInfo(Object o,String propertyName) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        BeanInfo bi = getBeanInfo(o.getClass());
        PropertyDescriptor[] propertyDescriptors = bi.getPropertyDescriptors();
        Object val = null;
        if(propertyDescriptors != null && propertyDescriptors.length>0){
            for(PropertyDescriptor pd : propertyDescriptors){
                if(pd.getName().equals(propertyName)){
                    Method method = pd.getReadMethod();
                    val = method.invoke(o,propertyName);
                    break;
                }
            }
        }
        return val;
    }

}


上面的代码仅仅是简单的实现,并没有考虑复杂的情况,也仅仅是做个原理性了解

猜你喜欢

转载自blog.csdn.net/shmily_lsl/article/details/80763909