前言
关于jdk实现代理模式的AOP代理和详解主要放在本文中:设计模式——代理模式:JDK静态代理和动态代理的实例和实现。本文相对于jdk的代理模式,内容较为少,主要体现cglib代理模式实现动态代理AOP和cglib实现动态代理AOP的区别以及实例Demo。
CGLIB和JDK实现AOP的区别
JDK动态代理只能为接口实现动态代理
。而不能对没有通过接口定义业务方法的类动态代理(因为jdk代理实现的实例对象会继承Proxy类
,java的单继承原则使得他不能代理实现继承类对象);
JDK的动态代理通过ProxyGenerator.generateProxyClass()生成代理类的字节码,由Proxy.defineClass0()加载,可以看到这个代理类 extends Proxy implements Interface1, … {…}。
所以在jdk代理实现一文中实现的代理类对象都是实现接口:
public class Boy implements Human,YoungMan{
Cglib:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理。是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法的增强,但是因为采用的是继承,所以该类或方法最好不要生成final。对于final类或方法,是无法继承的。
什么时候使用jdk动态代理?什么时候使用cglib动态代理?
以Spring的Bean对象来举例:
- 目标对象实现了接口,默认用JDK动态代理;
- 目标对象实现了接口,可强制使用CGLIB动态代理;(在spring配置中加入<aop:aspectj-autoproxy proxyt-target-class=”true”/>)
- 目标对象没有实现接口,必须采用CGLIB动态代理;
示例代码
实体类
public class Man {
public void sayHello(){
System.out.println("Hello Cglib");
}
}
cglib代理类
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
//设置需要创建子类的类
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
//拿到一个cglib动态生成的代理类(这个类继承自被代理类)
return enhancer.create();
}
/**自定义的前缀方法**/
private void pre() {
System.out.println("pre");
}
private void after() {
System.out.println("after");
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
this.pre();
System.out.println("前置代理");
//通过代理类调用父类中的方法
Object result = methodProxy.invokeSuper(o, objects);
System.out.println("后置代理");
this.after();
return result;
}
}
测试类
public class CglibMain {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
//通过生成子类的方式创建代理类
Man proxyImp = (Man) proxy.getProxy(Man.class);
proxyImp.sayHello();
}
}