切面代理工具-ProxyUtil

    • 我们定义一个接接口:
    • 定义一个实现类:
    1. @Override
    2. public void eat() {
    3. }
    4. }
    • 我们使用这个切面代理上述对象,来统计猫吃鱼的执行时间:
    1. Animal cat = ProxyUtil.proxy(new Cat(), TimeIntervalAspect.class);
    2. cat.eat();

    执行结果为:

    1. 猫吃鱼
    2. Method [cn.hutool.aop.test.AopTest$Cat.eat] execute spend [16]ms

    使用Cglib实现切面

    使用Cglib的好处是无需定义接口即可对对象直接实现切面,使用方式完全一致:

    • 引入Cglib依赖
    1. <groupId>cglib</groupId>
    2. <version>3.2.7</version>
    3. </dependency>
    • 定义一个无接口类(此类有无接口都可以)
    1. Dog dog = ProxyUtil.proxy(new Dog(), TimeIntervalAspect.class);
    2. String result = dog.eat();
    1. 狗吃肉

    ProxyUtil中还提供了一些便捷的Proxy方法封装,例如newProxyInstance封装了Proxy.newProxyInstance方法,提供泛型返回值,并提供更多参数类型支持。

    • 根据传入的interfaces动态生成一个类,实现interfaces中的接口
    • 通过传入的classloder将刚生成的类加载到jvm中。即将$Proxy0类load
    • 调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,并生成实现方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法。
    • 将$Proxy0的实例返回给客户端。