Spring AOP基础—JDK动态代理

JDK动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。

首先写一个接口 ForumService.java 及其实现类 ForumServiceImpl.java ,主要包括二个方法,删除主题removeTopic 和 删除 removeForum。代码如下:

public class ForumServiceImpl implements ForumService {

    @SuppressWarnings("static-access")
    public void removeForum(int forumId) {
        System.out.println("模拟删除Forum记录:" + forumId);
        try {
            Thread.currentThread().sleep(20);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("static-access")
    public void removeTopic(int topicId) {
        System.out.println("模拟删除Topic记录:" + topicId);
        try {
            Thread.currentThread().sleep(40);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

现在需要对二个方法的执行效率进行监控,所以创建一个监控方法效率的类 PerformanceMonitor.java 和 一个辅助工具类 MethodPerformance.java。代码如下:

public class MethodPerformance {
    private long begin;
    private long end;
    private String serviceMethod;
    public MethodPerformance(String serviceMethod){
        this.serviceMethod = serviceMethod;
        this.begin = System.currentTimeMillis();
    }
    public void printPerformance(){
        end = System.currentTimeMillis();
        long elapse = end - begin;
        System.out.println(serviceMethod + "花费" + elapse + "毫秒");
    }
}
public class PerformanceMonitor {
    private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
    
    public static void begin(String method){
        System.out.println("begin monitor……");
        MethodPerformance mp = new MethodPerformance(method);
        performanceRecord.set(mp);
    }
    public static void end(){
        System.out.println("end monitor……");
        MethodPerformance mp = performanceRecord.get();
        mp.printPerformance();
    }
}
为了将监控方法效率的代码织入到业务方法 removeTopic 和 removeForum中,我们创建代理类 PerformanceHandler.java,代码如下:
public class PerformanceHandler implements InvocationHandler {
    private Object target;
    public PerformanceHandler(Object target) {
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        PerformanceMonitor.begin(target.getClass().getName() + "." + method.getName());
        Object obj = method.invoke(target, args);
        PerformanceMonitor.end();
        return obj;
    }
}

首先,我们实现InvocationHandler接口,该接口定义了一个invoke(Object proxy,Method method,Object[] args)方法,proxy是最终生成的代理实例,一般不会用到;method是被代理目标实例的某个具体方法,通过它可以发起目标实例方法的反射调用;args是通过被代理实例某一个方法的入参,在方法 反射调用时使用。

此外,我们再构造函数里通过target传入希望被代理的目标对象,在InvocationHandler()接口方法invoke(Object proxy,Method method,Object[] args)里,将目标实例传给method.invoke()方法,调用目标实例的方法。

下面,我们通过Proxy结合PerformanceHandler创建ForumService接口的代理实例,这个代理实例实现了目标业务类的所有接口,即ForumServiceImpl的ForumService接口。这样我们就可以按照调用ForumService接口实例相同的方式调用代理实例。代码如下:

public class TestForumService {
    public static void main(String[] args) {
        ForumService target = new ForumServiceImpl();
        PerformanceHandler handler = new PerformanceHandler(target);
        ForumService proxy = (ForumService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
        proxy.removeForum(1001);
        proxy.removeForum(100);
    }
}

执行结果如下:

begin monitor……
模拟删除Forum记录:1001
end monitor……
com.aop.ForumServiceImpl.removeForum花费16毫秒
begin monitor……
模拟删除Forum记录:100
end monitor……
com.aop.ForumServiceImpl.removeForum花费15毫秒

你可能感兴趣的:(Spring AOP基础—JDK动态代理)