博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
来,带你手撕一个AOP
阅读量:6910 次
发布时间:2019-06-27

本文共 2812 字,大约阅读时间需要 9 分钟。

本文主要讲的是如何使用JDK动态代理实现简单的AOP。AOP是啥?如果你想在某些方法执行前后插入一些通用的处理,你可以考虑AOP。

预备知识

Proxy

JDK中提供了一个Proxy类用于创建动态代理对象的静态方法,如果在程序中为一个或多个接口动态地生成实现类,就可以使用Proxy来创建动态代理类。 Proxy提供了下面的方法来创建动态代理实例:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

该代理对象的实现类实现了interfaces所指定的系列接口,执行代理对象的每个方法时都会被替换执行InvocationHandler对象的invoke方法

InvocationHandler

InvocationHandler是一个接口,在创建动态代理实例的时候需要把一个InvocationHandler的实现类传进去,那么执行代理对象的每个方法时就会被替换成执行InvocationHandler实现类中的invoke方法,至于这个invoke方法要怎么实现,就由用户自己决定。

反射中Method的invoke()

java.lang.reflect.Method包中有一个方法

public Object invoke(Object obj, Object... args)

该方法可以实现对象方法的调用,它是Method类的实例方法,该方法中的参数obj是调用方法的对象,args是用于方法调用的参数。

实现过程

Pig接口,就定义了两个方法

public interface Pig {    void info();    void run();}复制代码

Pig的实现类,我们要做的就是在这两个方法执行的前后插入自己一些额外的操作

public class FatPig implements Pig {    @Override    public void info() {        System.out.println("我是一头小肥猪!");    }    @Override    public void run() {        System.out.println("我要跑步啦!");    }}复制代码

LogUtils,需要在代理对象方法执行前后调用的方法

public class LogUtils {    public void before() {        System.out.println("==== 方法开始执行 ====");    }    public void after() {        System.out.println("==== 方法执行结束 ====");    }}复制代码

PigInvocationHandler,该类实现了InvocationHandler接口。我们定义了一个Object类型的实例变量,因为我们需要在invoke方法中调用被代理对象的实现类的对应的方法。在invoke方法中,有两个关键的参数:method代表正在执行的方法,args代表调用目标方法时传入的实参。然后我们就可以在执行代理对象的方法前后自由插入自己的方法了。

public class PigInvocationHandler implements InvocationHandler {    // 需要被代理的对象    private Object target;    public void setTarget(Object target) {        this.target = target;    }    // 执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        LogUtils logUtils = new LogUtils();        // 执行logUtils对象中的before方法        logUtils.before();        // 以target作为主调来执行method方法        Object result = method.invoke(target, args);        // 执行logUtils对象中的after方法        logUtils.after();        return result;    }}复制代码

测试类

public class MyProxyFactory {    // 为指定的target生成动态代理对象    public static Object getProxy(Object target) {        PigInvocationHandler handler = new PigInvocationHandler();        // 为handler设置target对象        handler.setTarget(target);        // 创建并返回一个动态代理        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);    }    public static void main(String[] args) throws Exception {        // 创建一个原始的FatPig对象,作为target        Pig target = new FatPig();        // 以指定的target来创建动态代理对象        Pig pig = (Pig) MyProxyFactory.getProxy(target);        pig.info();        pig.run();    }}复制代码

运行结果:

==== 方法开始执行 ====

我是一头小肥猪!
==== 方法执行结束 ====
==== 方法开始执行 ====
我要跑步啦!
==== 方法执行结束 ====

上面实现了简单的AOP功能,我们可以在invoke方法里面加上更多的判断,使得功能更加强大,例如可以根据method参数指定某些方法前后执行特殊的处理。

转载地址:http://kegdl.baihongyu.com/

你可能感兴趣的文章
AndroidStudio下gradle的入门介绍与使用
查看>>
ZOJ - 3469 Food Delivery(区间DP)
查看>>
machine_learning-knn算法具体解释(近邻算法)
查看>>
selenium测试(Java)--下载文件(十六)
查看>>
Android真机调试访问本地服务器(localhost)的解决方案
查看>>
在QT和SDL搭建的框架中使用OPENGL在SDL窗口上进行绘图
查看>>
Golang协程与通道整理
查看>>
Linux学习必备
查看>>
ActiveMQ入门实例
查看>>
怎么WordPress增加在线投稿功能
查看>>
《转》Logistic回归 多分类问题的推广算法--Softmax回归
查看>>
php -- 断点调试 之 选择合适的xdebug
查看>>
PyCharm快捷键
查看>>
FTP服务器配置和管理
查看>>
cruise-control
查看>>
Python log() 函数
查看>>
JS组件系列——显示隐藏密码切换的jQuery插件
查看>>
PaaS 调研:GAE与 AWS(上)
查看>>
Arcgis栅格时序地图制作---时间轴动态展示多期影像
查看>>
第十一章 dubbo通信框架-netty4
查看>>