jdk的动态代理

        自Java1.3以后,Java提供了动态代理技术,允许开发者在运行期创建接口的代理示例。在sun刚推出动态代理时,还很难想象它有多大的实际用途,现在终于发现动态代理技术是实现AOP的绝好底层技术。

1.InvocationHandler接口

        InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态的将横切逻辑和业务逻辑编织在一起。InvocationHandler接口也被称为拦截器。

2.Proxy类

        Proxy利用InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。这样描述可能很抽象,我们通过demo代码示例来解释。

3.代码示例

1)业务接口

/**
 * 支付接口
 */
public interface IPay {

    public void wechatPay();
}

2)支付接口的业务类实现

package com.zhangzz.service.impl;

import com.zhangzz.service.IPay;

/**
 * 支付实现接口
 */
public class PayImpl implements IPay {

    @Override
    public void wechatPay() {
        System.out.println("欢迎使用微信支付!");
    }
}

3)横切逻辑InvocationHandler接口实现

package com.zhangzz.invocation;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class CommonHandler implements InvocationHandler {

    /**
     * 需要增强的目标类
     */
    private Object target;

    /**
     * 保存业务方法执行的开始时间
     */
    private final ThreadLocal local = new ThreadLocal();

    /**
     * 通过该构造方法将目标类传进来。
     * @param obj
     */
    public CommonHandler(Object obj){
        this.target = obj;
    }

    /**
     *
     * @param proxy 最终生成的代理实例
     * @param method 代理目标实例的某个方法,通过该参数可以发起目标实例方法的反射调用
     * @param args 被代理实例某个方法的入参,再方法反射调用时使用。
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始执行");
        local.set(System.currentTimeMillis());
        //通过反射机制调用目标类的业务方法,该行注释以上的代码为AOP的前置增强代码逻辑
        Object obj = method.invoke(target,args);
        //下面的为后置增强逻辑
        System.out.println("执行时间为:"+(System.currentTimeMillis()-local.get())+"ms");
        return obj;
    }
}

3)代理目标类,实现代理示例

package com.zhangzz;

import com.zhangzz.invocation.CommonHandler;
import com.zhangzz.service.IPay;
import com.zhangzz.service.impl.PayImpl;

import java.lang.reflect.Proxy;

public class Test {

    public static void main(String[] args) {
        //希望被代理的目标业务类
        IPay pay = new PayImpl();
        //Proxy.newProxyInstance(...)的第一个参数,必须为目标类的类加载器,第二个参数为目标类的接口(数组),第三个为横切类的实例
        IPay proxyPay = (IPay) Proxy.newProxyInstance(pay.getClass().getClassLoader(),pay.getClass().getInterfaces(),new CommonHandler(pay));
        proxyPay.wechatPay();
    }

}

通过以上代码结合注释,应该能很容易理解jdk的动态代理了。在横切的前置增强和后置增强,可以很轻松插入额外的逻辑,如事务管理、性能监控、权限控制等,完成我们重复的横切逻辑代码。

你可能感兴趣的:(java,开发语言)