紧连上等同篇随笔《自在了解Spring中之支配反转和靠注入》讲解了SpringIOC和DI的基本概念,这篇稿子我们学一下SpringIOC的行事体制,使我们越深入的敞亮其中的劳作。

  类之间的结构图如下

    图片 1

图片 2

   以下是代码

  

   BeanFactor接口:在Spring源码中的概念是:持有对自然数额的Bean的定义,同时每个Bean都让唯一标识的靶子(类),需要实现那接口。依照对Bean的概念,该工厂将会回一个暗含Bean定义之对象的独实例(原型设计形式),或者单例共享(一个毋庸置疑的单例设计形式,)范围是周工厂的界定(也可以知道成是不折不扣容器下),重回哪个种类档次的实例倚重让Bean工厂的布局:API是平之。因为Spring2.0遭扩充了指范围,可以遵照现进行使及下问(如以Web环境遭到的请求和对话),BeanFactory是应用程序组件之中心注册中心以及汇总布局。简单的吧该接口定义了得到Bean的法门,由子类去实现。

 

package ioc.factory;

/**
 * Created by zzf on 2016/10/26.
 */
public interface BeanFactory {
    /**
     * 根据对象的ID标识获取对象实例
     * @param name
     * @return
     */
    Object getBean(String name);
}

 

  BeanInfo类:使用Hash
Map
进行仓储Bean的音信,注意假使储存了Bean定义的Class类路径,这样才会经过取得type从而使反射实例化所定义的Bean。

  

package ioc.info;

import java.lang.Object;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by zzf on 2016/10/26.
 */
public class BeanInfo {
    private String id;
    private String type;
    private Map<String,Object> properties=new HashMap<String,Object>();

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Map<String, Object> getProperties() {
        return properties;
    }

    public void setProperties(Map<String, Object> properties) {
        this.properties = properties;
    }
    public void addProperty(String name, Object object)
    {
        this.properties.put(name, object);
    }
}


  Person:xml文件中定义的Bean

package ioc.bean;

/**
 * Created by zzf on 2016/10/26.
 */
public class Person {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

 

 

  AbstractBeanFactory接口:凡贯彻BeanFactory接口的抽象基类。实现获取Bean定义之点子。是落实逻辑的最重点一个近似,注册、读取、分析、注入都是于这么些类似及的章程调用的,具体可依照章程寻找。是最好顶层的IOC,实现该类负责从注册器中取出注册对象,和贯彻自目标描述音信转换为目标实例的长河实现基于名称获取对象的方法。

  虚幻方法setReader:由子类决定使应用什么的登记读取器,那里以了模版方法,父类定义抽象方法,但付出子类自由去规划艺术内容,即到由子类自己去摘SourceReader的落实类似。

  parseBead方法:剖析生成并转对象实例,重要通过映完成,依据类名,加载指定类,并赢得该类的Class对象下Class对象实例化该类,获取一个靶。逐个设置对象字段的价值,这里运用反射调用setter
Method形式

  loadBeans方法:在SourceReader的实现类似吃所实现,重要效用是加载Xml中所定义的Bean内容,并将其性音讯存入BeanInfo类中。

  parseBean(beanInfo):分析在loadBeans方法所存入BeanInfo,并经反射调用注入到Person类中。

  

package ioc.factory;

import ioc.info.BeanInfo;
import ioc.reader.SourceReader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * Created by zzf on 2016/10/26.
 */
public abstract class AbstractBeanFactory implements BeanFactory {
    private  String filePath;
    private Map<String,BeanInfo> container;
    protected SourceReader reader;
    public AbstractBeanFactory(String filePath){
        this.filePath=filePath;

    }

    /**
     * 
     * @param reader
     */
    protected abstract void setReader(SourceReader reader);


    //注册bean
    public void registerBeans(){
        this.container=this.reader.loadBeans(filePath);
    }

    @Override
    public Object getBean(String name) {
        BeanInfo beanInfo=this.container.get(name);
        if(beanInfo==null){
            return null;

        }else {
            return this.parseBean(beanInfo);
        }

    }

    /**
     * 
     * @param beanInfo 指定对象的描述信息
     * @return
     */
    protected  Object parseBean(BeanInfo beanInfo){
        Class clazz;
        try {
            //加载Bean的实例
            clazz=Class.forName(beanInfo.getType());
            Object bean=clazz.newInstance();

            //获取该对象下的所有方法,包括私有
            Method[] methods=clazz.getDeclaredMethods();

            for (String property:beanInfo.getProperties().keySet()){
                String setter="set"+ firstCharToUp(property);
                for(Method method:methods){
                    String methodName=method.getName();

                    if(methodName.equals(setter)){
                        Object value=beanInfo.getProperties().get(property);
                        //使用反射调用set方法
                        method.invoke(bean,value);
                    }
                }
            }
            return bean;

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
            return null;
    }

    private String firstCharToUp(String property) {
        System.out.println(property);
        char [] c=property.toCharArray();
        String first=String.valueOf(c[0]).toUpperCase();
        c[0]=first.charAt(0);
        System.out.println(String.valueOf(c));
        return String.valueOf(c);
    }
}
  

SourceReader:注册读取器接口,设计顶层读取器的抽象方法,负责读取用户注册的对象,继承该接口的类可以实现多种读取方式,如从配置文件中读取,根据标注读取,从网络中读取等等

package ioc.reader;

import ioc.info.BeanInfo;

import java.util.Map;

/**
 * Created by zzf on 2016/10/26.
 *
 */
public interface SourceReader {
    Map<String,BeanInfo> loadBeans(String filePath);
}

 

   XMLContext:XML的上下文,继承了AbstractBeanFactory,里面相比根本的点子是set里德r(),在父类中该情势是抽象方法,
这样的开的含义是交由子类实现好所想倘诺的读取形式。该方法中指明注册读取器(这里运用的XML,读者可依照兴趣去贯彻另外的措施如注)并于构造该法时几次性加载注册的目的。

  

package ioc.context;

import ioc.factory.AbstractBeanFactory;
import ioc.reader.SourceReader;
import ioc.reader.XMLSourceReader;

/**
 * Created by zzf on 2016/10/26.
 * 上下文的构造方法
 * 
 */
public class XMLContext extends AbstractBeanFactory{


    public XMLContext(String filePath){
        super(filePath);
        this.setReader(new XMLSourceReader());
        super.registerBeans();
    }

    @Override
    protected void setReader(SourceReader reader) {
        super.reader=reader;
    }
}

 

 

  XmlContext类:接轨了AbstractBeanFactory抽象类,举办Bean的注册与注册XML的读取器,注意再次来到的凡Map<String,
BeanInfo>

  

package ioc.reader;

import ioc.info.BeanInfo;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

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

/**
 * Created by zzf on 2016/10/26.
 * 使用 dom4j进行Xml的读取操作
 */
public class XMLSourceReader implements SourceReader {

    @Override
    public Map<String, BeanInfo> loadBeans(String filePath) {
        //读取指定的配置文件
        SAXReader reader = new SAXReader();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        //从class目录下获取指定的xml文件
        InputStream ins = classLoader.getResourceAsStream(filePath);
        Document doc = null;
        try {
            doc = reader.read(ins);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        //获得根节点
        Element root = doc.getRootElement();
        Map<String,BeanInfo>beanInfoMap=new HashMap<String, BeanInfo>();
        //遍历bean
        for (Iterator i = root.elementIterator("bean"); i.hasNext();){
            Element element = (Element) i.next();
            //获取bean的属性id和class
            Attribute id = element.attribute("id");
            Attribute cls = element.attribute("class");
            try {
                //利用Java反射机制,通过class的名称获取Class对象
                Class bean=Class.forName(cls.getText());
                //获取对应class的信息
                java.beans.BeanInfo info= Introspector.getBeanInfo(bean);
                //获取其属性描述
                PropertyDescriptor [] propertyDescriptors=info.getPropertyDescriptors();
                Method method;
                Object object=bean.newInstance();
                BeanInfo beanInfo=new BeanInfo();
                for(Iterator iterator=element.elementIterator("property");iterator.hasNext();){
                    Element foo2= (Element) iterator.next();
                    //获取该property的name属性
                    Attribute name = foo2.attribute("name");

                    String value = null;
                    //获取该property的子元素value的值
                    for(Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
                        Element node = (Element) ite1.next();
                        value = node.getText();
                        break;
                    }
                    System.out.println("name:"+name.getText()+"value"+value);
                for (int j=0;j<propertyDescriptors.length;j++){
                    if(propertyDescriptors[j].getName().equalsIgnoreCase(name.getText())){
                        method=propertyDescriptors[j].getWriteMethod();
                        //利用Java的反射极致调用对象的某个set方法,并将值设置进去
                        method.invoke(object,value);
                        //将获取的对象属性信息存入我们自定义的BeanInfo当中
                        beanInfo.addProperty(name.getText(),value);
                }
                }

                    beanInfo.setId(id.getText());
                    beanInfo.setType(cls.getText());
                    beanInfoMap.put(id.getText(),beanInfo);
                }
                return beanInfoMap;
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IntrospectionException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }

        return null;
    }
}

  

<?xml version="1.0" encoding="UTF-8"?>

<beans>
    <bean id="person" class="ioc.bean.Person">
        <property name="username">
            <value>zzf</value>
        </property>
        <property name="password">
            <value>12345678</value>
        </property>
    </bean>
</beans>

package ioc;

import ioc.bean.Person;
import ioc.context.XMLContext;
import ioc.factory.BeanFactory;

/**
 * Created by zzf on 2016/10/26.
 */
public class test {
    public static void main(String[] args) {
        BeanFactory factory=new XMLContext("configuration/config.xml");
        Person person= (Person) factory.getBean("person");
        System.out.println(person.getPassword());
        System.out.println(person.getUsername());
    }
}

 

 执行main方法后,控制台成功输出xml所定义之性。

图片 3

  全部的贯彻过程要分以下几步,1.朗诵取Xml文件,怎么读取?(看代码) 2.诵读博了之后吧?应该发个容器临时存放一下,从而实现方便传递,这里运用的HashMap,从中也堪看到为啥要用BeanInfo类来存放类的音,3.分析Map<String,BeanInfo>容器,提取里面的Bean属性,4.领取后,通过反射方法注入及Person类中,从而就实现了username和password属性的流入了。

  再结自己首先首所讲的SpringIOC概念讲解,相信读者应当会清晰的认识的IOC的效用以及大约的落实过程。

 

相关文章

网站地图xml地图