Java动态代理(三)——Cglib动态代理

一、Cglib动态代理
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用Cglib即使代理类没有实现任何接口也可以实现动态代理功能。而且,它的运行速度要远远快于JDK的Proxy动态代理。

1.Cglib核心类

  • net.sf.cglib.proxy.Enhancer //主要的增强类
  • net.sf.cglib.proxy.MethodInterceptor //主要的方法拦截类,它是Callback接口的子接口,需要用户实现。这个接口只定义了一个方法
  • public Object intercept(Object object, java.lang.reflect.Method method,Object[] args, MethodProxy proxy) throws Throwable;//第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数
  • net.sf.cglib.proxy.MethodProxy //JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用

2.上篇PersonSerivice的Cglib代理实现(实现的前提是导入了Spring框架下的jar包)
被代理的类:

public class PersonServiceImp {
private String name;
private Integer age;

public PersonServiceImp() {
super();
}

public PersonServiceImp(String name, Integer age) {
super();
this.name = name;
this.age = age;
}

public String getName() {
System.out.println("---------getName------");
return name;
}

public Integer getAge() {
System.out.println("---------getAge--------");
return age;
}

public void setName(String name) {
this.name = name;
}

public void setAge(Integer age) {
this.age = age;
}
}

代理的类:

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class MyMethodInterceptor implements MethodInterceptor {

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("getName".equals(method.getName())) {
System.out.println("*********before*******");
System.out.println("method:" + method);
Object res = methodProxy.invokeSuper(obj, args);
System.out.println("*********after********");
return res;
} else {
Object res = methodProxy.invokeSuper(obj, args);
return res;
}
}

}

 

测试:

import org.springframework.cglib.proxy.Enhancer;

public class CglibProxyTest {
public static void main(String[] args) {
PersonServiceImp person = new PersonServiceImp();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(PersonServiceImp.class);
enhancer.setCallback(new MyMethodInterceptor());
person = (PersonServiceImp) enhancer.create();
person.setName("jack");
person.setAge(20);
System.out.println(person.getClass().getName());
System.out.println(person.getName());
System.out.println(person.getAge());
}
}

  

输出结果:

二、Jdk动态道理和Cglib动态代理的区别
1.JDK动态代理是利用反射机制实现的,在调用具体方法前调用InvokeHandler来处理。而Cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
2.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP,也可以强制使用CGLIB实现AOP;如果目标对象没有实现接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换。
3.JDK动态代理只能对实现了接口的类生成代理,而不能针对类;CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法, 因为是继承,所以该类或方法不要声明成final。

4.使用CGLib实现动态代理,CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。

猜你喜欢

转载自www.cnblogs.com/ericz2j/p/10439407.html