本身實現的一個過濾器的例子

    工做中要開發一個小的功能,我並沒用立刻去實現,而是想了想看看能不能作的更有擴展性一些。固然思考的結果有多是過分的設計了。java

     如今把功能要求簡單描述一下,而後在說實現方法:node

     系統接受到一個XML格式的消息體,而後須要根據一些需求把XML消息作一些過濾,修改,而後存儲起來。spring

     實現的大概思路就是用過濾器的思想再加上邏輯插件化。apache

     下面就是代碼骨架:    dom

public interface XMLAdapter {
    public boolean update(XMLDocument targetDocument);
}

     上面的接口是咱們的邏輯要實現。XMLDocument 是XML用dom4j解析以後的類。相似於一個java bean。ide

import org.apache.log4j.Logger;

public class ExampleAdapter implements XMLAdapter {
    
	private String nodesValue;	
	private String nodeValue;
	private static Logger logger = Logger.getLogger(ExampleAdapter.class);
	

	@Override
	public boolean update(XMLDocument targetDocument) {
            //our logic is implemented here
	}
	

	public String getNodesValue() {
		return nodesValue;
	}

	public void setNodesValue(String nodesValue) {
		this.nodesValue = nodesValue;
	}

	public String getNodeValue() {
		return nodeValue;
	}

	public void setNodeValue(String nodeValue) {
		this.nodeValue = nodeValue;
	}
	
}

這是一個實現類。對XML的操做:過濾節點,刪除節點,修改節點的工做都在update方法裏面實現。這個類有兩個成員。update方法裏面用這兩個成員來作一些邏輯。這裏咱們用注入的方式來給這兩個成員賦值。

下面是注入的一個簡單實現:this

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="exampleAdapter" class="com.example.ExampleAdapter">
        <property name="nodesValue">
            <value>XXX</value>
        </property>
        <property name="nodeValue">
            <value>YYY</value>
        </property>
    </bean>
</beans>

對spring熟悉的人看到這個XML配置文件應該很熟悉了。下面是這個XML文件對應的工廠類。

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.Attribute;
public class AdapterFactory {

    private Map<String, Object> adapterMap = new ConcurrentHashMap<String, Object>();
    private static Logger logger = Logger.getLogger(AdapterFactory.class);
	
	/**
	 * init AdapterFactory. parse adapter.xml to bean map.
	 * @param filePath Adaptor configuration file path.
	 */
    public void init(String filePath) {
        if (filePath == null || filePath.length() == 0) {
            logger.warn("empty configuration file path and name!");
            return;
        }
        try {
            SAXReader reader = new SAXReader();
            InputStream ins = new FileInputStream(filePath);
            Document doc = reader.read(ins);
            Element root = doc.getRootElement();  
            Element attributeElement;
            for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
		attributeElement = (Element) i.next();
                Attribute id = attributeElement.attribute("id");  
                Attribute cls = attributeElement.attribute("class");
               
                Class adaptor = Class.forName(cls.getText());
                java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(adaptor);
                java.beans.PropertyDescriptor[] pd = info.getPropertyDescriptors();
                Method mSet = null;
                Object obj = adaptor.newInstance();
               
                for (Iterator ite = attributeElement.elementIterator("property"); ite.hasNext();) {  
                    Element propertyElement = (Element) ite.next();
                    Attribute name = propertyElement.attribute("name");
                    String value = null;
                      
                    for (Iterator ite1 = propertyElement.elementIterator("value"); ite1.hasNext();) {
                        Element node = (Element) ite1.next();
                        value = node.getText();
                        break;
                    }
                      
                    for (int k = 0; k < pd.length; k++) {
                        if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                            mSet = pd[k].getWriteMethod();
                            mSet.invoke(obj, value);
                        }
                    }
                }
                adapterMap.put(id.getText(), obj);
            }
        } catch (Exception e) {
            logger.warn("init AdaptorFactory failed", e);
        }
		
    }
	
    public Map<String, Object> getAdapterMap() {
        return adapterMap;
    }
}

這個類說白了就是經過反射把XML文件配置的類load到一個Map中。

 能夠參考下面這篇blog對這個類的說明spa

http://blog.csdn.net/wwww1988600/article/details/7286887.net

這樣經過AdapterFactory咱們就能夠拿到全部的咱們配置的類。下面就是在咱們的主邏輯中把咱們XML配置的這些類調起來。這裏有一個想法:當咱們有新需求時,在XML配置文件添加一些實現類時,咱們的主邏輯代碼可不能夠不修改?插件

因此就引入下面這個類:

import java.util.Map;
import org.apache.log4j.Logger;
public class ExampleFilterChain {
	
    private static Logger logger = Logger.getLogger(ExampleFilterChain.class);
    private static AdapterFactory adapterFactory;
    private static ExampleFilterChain filterChain ;
	
    private ExampleFilterChain(String filePath) {
        init(filePath);
    }

    public static synchronized ExampleFilterChain getInstance(String filePath) {
        if(filterChain == null) {
	    filterChain = new ExampleFilterChain(filePath);
	}
	return filterChain;
    }

    /**
     * 
     * @param filePath AdapterFactory configuration files
     */
	private void init(String filePath) {
	    adapterFactory = new AdapterFactory();
	    adapterFactory.init(filePath);
	}
	
	/**
	 * this method will issue all adapter instances which defined in adapter.xml
	 */
	public void filter(XMLDocument targetDocument){
	    Map<String,Object> maps = adapterFactory.getAdapterMap();
	    if(maps == null || maps.size() == 0){
                logger.info("can not find any adapter instances");
		return;
	    }
	    Object[] keys = maps.keySet().toArray();
	    for(Object key : keys){
	        ((XMLAdapter)maps.get(key)).update(target);
	    }
	}
}

這個類的做用就是初始化咱們的AdaperFactory。他有一個public方法:filter()。這個方法把咱們load進來的全部的實現類都執行一遍。這裏留下一些問題:當一個實現類執行失敗後,後面的實現類要不要繼續執行,等等吧。之後在考慮。

下面的工做就簡單了,在主邏輯裏面調用這個ExampleFilterChain的filter方法就能夠了。

private ExampleFilterChain chain = ExampleFilterChain.getInstance(adapter.xml");

.....
chain.filter(xmlDocument);
.....

OK。結束。

這種實現的一個好處是:當咱們有新的需求時,只要實現XMLAdaper接口,並把實現類配置到adapter.xml中就能夠了。實現者不須要去修改主邏輯和其餘代碼。

相關文章
相關標籤/搜索