您的位置:首页 > 其它

如何利用动态代理技术构建一个通用的,获取代理类的简单框架?

2014-10-09 23:12 1061 查看
如果需要为许多方法添加额外的操作,就如数据库的事务日志,你需要对数据库的每一项操作都做个记录,

那么多的方法,如果手工编写的话,不仅费时,而且臃肿不堪。这时候java代理技术就起作用了,通过java的动态代理可以非常方便的为一个类的多种方法添加额外的操作。

在java中有一个类是 java.lang.reflect.Proxy;他的一个方法可以非常方便的创建代理对象

Objectjava.lang.reflect.Proxy.newProxyInstance(ClassLoader
loader, Class<?>[] interfaces,InvocationHandler
h) throwsIllegalArgumentException

它接收三个参数:

1.loader 代理目标类用哪个加载器加载,

2.interfaces 需要为目标类的哪些方法添加操作,通过传入目标类所实现的接口而获取

3.InvocationHandler 这是一个抽象类,你需要实现它的invoke() 方法用来添加额外的操作

在添加额外的操作时可以通过传入通告对象,执行通告对象的方法来实现。

有了这三样东西,就可以动态构建一个为目标类生产的代理对象了。

那么,为了将这些操作构建为一个框架,我们需要下面2个元素:

1. 代理目标:要为哪个类构建代理 (什么来加载器,接口,都可以通过反射反射该类得到)

2. 通告对象:所有的额外操作都可以通过调用该对象的方法实现

现在这些元素写在一个配置文件中,以便于更改 如下

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

config.propertice

className=java.util.ArrayList

class.Advice=MyAdvice

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

还可以直接指定目标类,和通告对象

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

setTarget(Object target)

setAdvice(Object advice)

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

有了这些元素,就可以开始编写代理类了

类结构上图



其中的方法getProxy()内部就是调用的newProxyInstance

=============分割线,下面是源代码=============================================

package zhangweiocng.autoProxy;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
import java.util.ArrayList;

/**
 *
 * 要想获得一个代理类,必须先传入一个配置好的文件,或者指定目标类和通告类
 * @author weicong
 *
 */
public class AutoProxy {
    
    private Object target;
    private Advice advice;
    
    private Properties properties;
    public Object getProxy(){
        
        Object clazz = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler(){
                    @Override
                    public Object invoke(Object proxy, Method method,
                            Object[] args) throws Throwable {
                        advice.beforeMethod(method);
                        
                        Object returnValue =method.invoke(target, args);
                        System.out.println("--executeMethod--"+method.getName());
                        advice.afterMethod(method);
                        return returnValue;
                    }
                }
            );
        return clazz;
    }
    public void setProperties(InputStream inStream){
        
        this.properties=new Properties();
        try {
            properties.load(inStream);
            
            target=getTarget();
            advice=getAdvice();
        } catch (IOException e) {
            System.out.println("未成功加载配置文件");
            e.printStackTrace();
        }
        
    }
    public Object getTarget()  {
        
        String targetName = properties.getProperty("className.target");
        Object target = null;
        try {
            Class clazz = Class.forName(targetName);
            target = clazz.newInstance();
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException e) {
            System.out.println("target类加载出错");
            e.printStackTrace();
        }
        return target;
    }
    public void setTarget(Object target) {
        this.target = target;
    }
    public Advice getAdvice() {
        String adviceName = properties.getProperty("className.advice");
        Advice advice = null;
        try {
            Class clazz = Class.forName(adviceName);
            advice = (Advice)clazz.newInstance();
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException e) {
            System.out.println("advice类加载出错");
            e.printStackTrace();
        }
        return advice;
    }
    public void setAdvice(Advice advice) {
        this.advice = advice;
    }
}
-----------------文件分割标记-----------------------------------------------------------
package zhangweiocng.autoProxy;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;

public class AutoProxyTest {

    public static void main(String[] args) {
        
        AutoProxy autoProxy=new AutoProxy();
        Advice advice=new MyAdvice();
        ArrayList arrayList=new ArrayList();
        InputStream inStream=null;
        Collection  proxy=null;
        /*
         * 通过配置文件指定目标类和通告类
         * try{
            inStream=new FileInputStream("config.properties");
            autoProxy.setProperties(inStream);
            proxy=( Collection )autoProxy.getProxy();
            
            proxy.add("123");
            proxy.add("456");
            System.out.println(arrayList.toString());
            System.out.println(arrayList.size());
            
            

        }catch(IOException e){
            System.out.println("文件不存在");
            e.printStackTrace();
        }*/
        /*显式指定目标类和通告类*/
        autoProxy.setTarget(arrayList);
        autoProxy.setAdvice(advice);
        proxy=(Collection )autoProxy.getProxy();
        
        proxy.add("123");
        proxy.add("456");
        System.out.println(arrayList.toString());
        System.out.println(arrayList.size());

    }

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