程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 簡單模擬SpringIOC工作機制流程開發,springioc機制

簡單模擬SpringIOC工作機制流程開發,springioc機制

編輯:JAVA綜合教程

簡單模擬SpringIOC工作機制流程開發,springioc機制


  緊接上一篇文章《輕松了解Spring中的控制反轉和依賴注入》講解了SpringIOC和DI的基本概念,這篇文章我們模擬一下SpringIOC的工作機制,使我們更加深刻的理解其中的工作。再上代碼之前我們先來看看幾個類的設計目的。 

  BeanFactor接口:在Spring源碼中的定義是:持有對一定數量的Bean的定義,同時每個Bean都被唯一標識的對象(類),需要實現這個接口。根據對Bean的定義,該工廠將會返回一個包含Bean定義的對象的獨立實例(原型設計模式),或者單例共享(一個不錯的單例設計模式,)范圍是整個工廠的范圍(也可以理解成是整個容器下),返回哪種類型的實例依賴於Bean工廠的配置:API是相同的。因為Spring2.0中擴大了依賴范圍,可以根據具體應用上下問(如在Web環境中的請求和會話),BeanFactory是應用程序組件的中央注冊中心和集中配置。簡單的來說該接口定義了獲取Bean的方法,由子類去實現。

  BeanFactory接口:是實現BeanFactory接口的抽象基類。實現獲取Bean定義的方法。

  XmlContext類:繼承了AbstractBeanFactory抽象類,進行Bean的注冊和注冊XML的讀取器。

  BeanInfo類:進行存儲Bean的信息。

  接下來上代碼,需要注釋的地方我都添加上去了,類的目錄如下。

    

  類之間的結構圖如下

   以下是代碼

  

package ioc.factory;

/**
 * Created by zzf on 2016/10/26.
 */
public interface BeanFactory {
    /**
     * 根據對象的ID標識獲取對象實例
     * @param name
     * @return
     */
    Object getBean(String name);
}
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.
 *
 * 最頂層的IOC實現
 * 該類負責從注冊器中取出注冊對象
 * 實現從對象描述信息轉換為對象實例的過程
 * 實現根據名稱獲取對象的方法
 *
 */
public abstract class AbstractBeanFactory implements BeanFactory {
    private  String filePath;
    private Map<String,BeanInfo> container;
    protected SourceReader reader;
    public AbstractBeanFactory(String filePath){
        this.filePath=filePath;
        setReader(reader);
    }

    /**
     * 由子類決定如果使用什麼樣的注冊讀取器
     * 這裡使用了模板方法,父類定義抽象方法,但交給子類自由去設計方法內容
     * @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);
        }

    }

    /**
     * 解析生成並生成對象實例
     * 主要通過反射完成
     * 根據類名,加載指定類,並取得該類的Class對象
     * 使用Class對象實例化該類,獲取一個對象。
     * 逐個設置對象字段的值,這裡采用setter Method方式
     *
     * @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);
    }
}
  

package ioc.context;

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

/**
 * Created by zzf on 2016/10/26.
 * 上下文的構造方法
 * 該方法中指明注冊讀取器(這裡采用的XML,讀者可以根據興趣去實現另外的方式如注解)
 * 並在構造該方法時一次性加載注冊的對象
 */
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;
    }
}

  

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

 

  

package ioc.context;

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

/**
 * Created by zzf on 2016/10/26.
 * 上下文的構造方法
 * 該方法中指明注冊讀取器(這裡采用的XML,讀者可以根據興趣去實現另外的方式如注解)
 * 並在構造該方法時一次性加載注冊的對象
 */
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;
    }
}
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);
    }
}
   

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

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved