切面代理工具-ProxyUtil
- 我们定义一个接接口:
- 定义一个实现类:
@Override
public void eat() {
}
}
- 我们使用这个切面代理上述对象,来统计猫吃鱼的执行时间:
Animal cat = ProxyUtil.proxy(new Cat(), TimeIntervalAspect.class);
cat.eat();
执行结果为:
猫吃鱼
Method [cn.hutool.aop.test.AopTest$Cat.eat] execute spend [16]ms
使用Cglib实现切面
使用Cglib的好处是无需定义接口即可对对象直接实现切面,使用方式完全一致:
- 引入Cglib依赖
<groupId>cglib</groupId>
<version>3.2.7</version>
</dependency>
- 定义一个无接口类(此类有无接口都可以)
Dog dog = ProxyUtil.proxy(new Dog(), TimeIntervalAspect.class);
String result = dog.eat();
狗吃肉
ProxyUtil中还提供了一些便捷的Proxy方法封装,例如newProxyInstance封装了Proxy.newProxyInstance方法,提供泛型返回值,并提供更多参数类型支持。
- 根据传入的interfaces动态生成一个类,实现interfaces中的接口
- 通过传入的classloder将刚生成的类加载到jvm中。即将$Proxy0类load
- 调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象,并且用interfaces参数遍历其所有接口的方法,并生成实现方法,这些实现方法的实现本质上是通过反射调用被代理对象的方法。
- 将$Proxy0的实例返回给客户端。