大话java之JDK动态代理

来源:互联网 发布:windows系统日志备份 编辑:程序博客网 时间:2024/05/18 03:13

上一篇讲到到java的代理模式以及java的静态代理的实现方式。静态代理的问题在于需要为每个委托类建立一个代理类,这样不仅耗费大量的精力,也不利于项目的解耦和维护。本篇就要讲讲java的动态代理,动态代理在spring等框架中十分重要,它不仅保留代理模式的优点,也更好地解耦项目,对于代码的复用和维护都是更有优势。

1.动态代理的简单例子

1)委托类接口

//委托类接口public interface TestService {    void business();}

2)委托类的实现

//委托类的实现类public class TestImplement implements TestService{    @Override    public void business() {        try{            System.out.println("do the busniess");            Thread.sleep(200);        }catch (Exception e) {            e.printStackTrace();        }    }}

3)处理类(和静态代理很大的区别就是处理类更通用)

public class LoggerInvocationHandler implements InvocationHandler {    private Object target;// 目标类    public LoggerInvocationHandler(Object target) {        this.target = target;    }    //这是一个简单的日志处理类,会记录方法的执行时间和耗时    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        Long timeStart = System.currentTimeMillis();        System.out.println("-- invoke start---timeStart="+timeStart);        Object result = method.invoke(this.target, args);        System.out.println("-- invoke finish---takes="+(System.currentTimeMillis()-timeStart));//记录方法的调用耗时        return result;    }}

4)测试代码

        TestService target = new TestImplement();        LoggerInvocationHandler myInterceptor = new LoggerInvocationHandler(target);        TestService proxyObj =  (TestService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInterceptor);          proxyObj.business();  

运行结果:

– invoke start—timeStart=1504015240306
do the busniess
– invoke finish—takes=201

这就是动态代理的一个简单的例子,它能记录方法执行的时间和耗时,并且LoggerInvocationHandler.class是通用的。

2.动态代理的原理

首先我们从入口开始看

        TestService proxyObj =  (TestService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), myInterceptor);  

点击进入Proxy.newProxyInstance()方法,先看下注释

    /**     * Returns an instance of a proxy class for the specified interfaces     * that dispatches method invocations to the specified invocation     * handler.     *     * <p>{@code Proxy.newProxyInstance} throws     * {@code IllegalArgumentException} for the same reasons that     * {@code Proxy.getProxyClass} does.     *     * @param   loader the class loader to define the proxy class     * @param   interfaces the list of interfaces for the proxy class     *          to implement     * @param   h the invocation handler to dispatch method invocations to     * @return  a proxy instance with the specified invocation handler of a     *          proxy class that is defined by the specified class loader     *          and that implements the specified interfaces

从注释可以看出这个方法,是给指定接口的代理类生成实例。比如我们前面传入的是TestService,那么就是返回TestService的代理类。这就是动态代理和静态代理的区别,静态代理需要我们自己写代理类,而动态代理是动态生成的。

更详细的动态代理原理可以参考 终点的博客

以上的动态代理方式委托类必须是接口,一般称作JDK动态代理。那么委托类如果不是接口该怎么办?这就需要CGLIB等方式

阅读全文
0 0
原创粉丝点击