AOP增强
aop除了代理增强之外还有其他的增强
方式一:ajc增强,没有利用到spring容器,而是用了ajc编译器来增强
方式二:agent类加载增强
aop代理增强-jdk的动态代理
是jdk自带的代理功能,只能针对接口代理。
产生代理需要用到jdk的Proxy中的newProxyInstance方法。
参数1-类加载器:因为相比于正常编写的Java代码,代理对象的生成是没有源码的,是在运行期间直接生成字节码文件,所以就需要一个类加载器去加载这个字节码文件
参数2-要实现的接口
参数3-invocationHandler接口:代理类创建出来,也实现了接口,还要实现接口中方法,这些方法的封装就封装在invocationHandler接口里面,具体的执行是invocationHandler接口的invoke方法。
这个invoke方法又有三个参数:
- proxy:代理对象自己
- method:正在执行的方法对象
- args:方法传过来的参数
public static void main(String[] param) throws IOException {
// 目标对象
Target target = new Target();
ClassLoader loader = JdkProxyDemo.class.getClassLoader(); // 用来加载在运行期间动态生成的字节码
Foo proxy = (Foo) Proxy.newProxyInstance(loader, new Class[]{Foo.class}, (p, method, args) -> {
System.out.println("before...");
// 目标.方法(参数)
// 方法.invoke(目标, 参数);
Object result = method.invoke(target, args);
System.out.println("after....");
return result; // 让代理也返回目标方法执行的结果
});
System.out.println(proxy.getClass());
proxy.foo();
System.in.read();
}
}
- 在jdk的动态代理中目标对象和代理对象是兄弟关系,所以不可以强制转换
- 目标对象可以是final对象
aop代理增强-cglib的动态代理
通过enhance类的create方法来创建代理对象,cglib通过父子继承关系来实现动态代理,所以create的两个参数
参数1:需要继承的父类,即目标对象的类
参数2:MethodInterceptor,类似于jdk中的invocationHandler接口,封装的是代理对象方法执行时的行为
这个接口的有四个参数
参数1:代理类自己
参数2:代理类中的方法
参数3:方法传过来的对象
参数4:可以认为是一个方法对象,可以避免反射调用
public class CglibProxyDemo {
static class Target {
public void foo() {
System.out.println("target foo");
}
}
// 代理是子类型, 目标是父类型
public static void main(String[] param) {
// Target target = new Target();
Target proxy = (Target) Enhancer.create(Target.class, (MethodInterceptor) (p, method, args, methodProxy) -> {
System.out.println("before...");
// Object result = method.invoke(target, args); // 用方法反射调用目标
// methodProxy 它可以避免反射调用
// Object result = methodProxy.invoke(target, args); // 内部没有用反射, 需要目标 (spring)
Object result = methodProxy.invokeSuper(p, args); // 内部没有用反射, 需要代理
System.out.println("after...");
return result;
});
proxy.foo();
}
}
代理类是子类,目标类是父类,所以目标类不能是final,不然代理类不能继承,同时目标类中方法也不能是final字段,因为子类重写了父类的方法,加了就不能重写了