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


如果需要为许多方法添加额外的操作,就如数据库的事务日志,你需要对数据库的每一项操作都做个记录,

那么多的方法,如果手工编写的话,不仅费时,而且臃肿不堪。这时候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)

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

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

类结构上图

autoProxy


 





其中的方法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());

    }

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值