Aop手动代理分为jdk动态代理和CGLIB代理
1、jdk动态代理是通过jdk中的java.lang.reflect.Proxy类来实行的,底层的原理是根据接口和增强的方法,创建一个新类,所以必须基于接口
2、CGLIB(code generation libray)是一个高性能开元的代码生成包,它的底层是通过ASM(一个小而快的字节码处理框架)来转换字节码,为一个类创建一个子类,然后对子类进行增强,解决jdk的无接口代理问题
区别:jak动态代理必须有一个接口,CGLIB可以直接代理一个类
代码演示
定义一个Teacher类,里面有一个start()方法
public void start() {
System.out.println("开始上课");
}
定义一个切面类
public class AspectJdk {
public void before() {
System.out.println("方法执行前");
}
public void after() {
System.out.println("方法执行后");
}
}
通过jdk动态代理
private static UserDao getUser(UserImpl userImpl, AspectJdk aspectJdk) {
return (UserDao) Proxy.newProxyInstance(userImpl.getClass().getClassLoader(), // 代理类的类加载器
new Class[] { UserDao.class }, // 有哪些接口,这个类必须有接口
new InvocationHandler() { // 方法增强
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// proxy不能用,因为proxy代表的是代理类,用的话会导致内存溢出
// method代表的是增强的方法
// args代表的是参数
aspectJdk.before();
Object object = method.invoke(userImpl, args);
aspectJdk.after();
return object;
}
});
}
通过CGLIB代理
public static Teacher getTeacher(Teacher teacher, AspectJdk aspectJdk) {
//参数:teacher:代表的是被代理的类 aspectJdk:代表的是切面
// Enhancer类 允许为非接口类型创建一个Java代理。
// Enhancer动态创建了给定类型的子类但是拦截了所有的方法。和Proxy不一样的是,不管是接口还是
类他都能正常工作。
Enhancer enhancer = new Enhancer();
// 设置代理类要要为谁代理
enhancer.setSuperclass(Teacher.class);
// 设置代理类的回掉函数
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy)
throws Throwable {
aspectJdk.before();
Object obj = method.invoke(teacher, args);
aspectJdk.after();
return obj;
}
});
return (Teacher) enhancer.create();
}