该系列文章主要是对 hutool 工具类的介绍,详情可以参考
2 hutool-aop
AOP模块主要针对JDK中动态代理进行封装,抽象动态代理为切面类Aspect,通过ProxyUtil代理工具类将切面对象与被代理对象融合,产生一个代理对象,从而可以针对每个方法执行前后做通用的功能。
在aop模块中,默认实现可以下两个切面对象:
- SimpleAspect 简单切面对象,不做任何操作,继承此对象可重写需要的方法即可,不必实现所有方法
- TimeIntervalAspect 执行时间切面对象,用于简单计算方法执行时间,然后通过日志打印方法执行时间
2.1 jdk 动态代理实现切面
定义一个接口
public interface Animal{
void eat();
}
定义一个实现类
public class Cat implements Animal{
@Override
public void eat() {
Console.log("猫吃鱼");
}
}
使用代理方式
Animal cat = ProxyUtil.proxy(new Cat(), TimeIntervalAspect.class);
cat.eat();
2.2 cglib 实现切面
默认使用 jdk 动态代理,这边需要额外引入第三方依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.7</version>
</dependency>
使用Cglib的好处是无需定义接口即可对对象直接实现切面,使用方式完全一致
定义一个普通类
public class Dog {
public void eat() {
Console.log("狗吃肉");
}
}
使用代理方式
Dog dog = ProxyUtil.proxy(new Dog(), TimeIntervalAspect.class);
dog.eat();
2.3 自定义切面
public class MyAspect extends SimpleAspect {
private String test;
public MyAspect(String test) {
super();
this.test = test;
}
@Override
public boolean before(Object target, Method method, Object[] args) {
Console.log("before:target:{},method:{},args:{},test:{}", target, method, args, test);
return super.before(target, method, args);
}
@Override
public boolean after(Object target, Method method, Object[] args, Object returnVal) {
Console.log("after:target:{},method:{},args:{},test:{}", target, method, args, test);
return super.after(target, method, args, returnVal);
}
@Override
public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
Console.log("before:target:{},method:{},args:{},exception:{}", target, method, args, e);
return super.afterException(target, method, args, e);
}
}
使用代理
Dog dog = ProxyUtil.proxy(new Dog(), new MyAspect("测试"));
dog.eat();
2.4 两种代理区别
- java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
- 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
查看源码
JDK 动态代理类
@Override
public <T> T proxy(T target, Aspect aspect) {
return ProxyUtil.newProxyInstance(//
target.getClass().getClassLoader(), //
new JdkInterceptor(target, aspect), //
target.getClass().getInterfaces());
}
CGlibProxy 动态代理类
@Override
@SuppressWarnings("unchecked")
public <T> T proxy(T target, Aspect aspect) {
final Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new CglibInterceptor(target, aspect));
return (T) enhancer.create();
}