性能优于JDK代理,CGLib如何实现动态代理

编程

动态代理" title="动态代理">动态代理三种方式

动态代理实现有三种方式,jdk动态代理(基于接口),cglib动态代理(基于继承),javassist(hibernate中使用这种方式)实现动态代理。

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢?

这就需要CGLib了。

cglib如何实现代理

Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。

CGLib原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLib在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLib合适,反之,使用JDK方式要更为合适一些。同时,由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。

cgLib动态代理实例

下面演示一个动态代理的实例。

导入maven 依赖

cglib 是基于asm 字节修改技术。导入 cglib 会间接导入 asm, ant, ant-launcher 三个jar 包。

<!-- cglib 动态代理依赖 begin -->

<dependency>

<groupId>cglib</groupId>

<artifactId>cglib</artifactId>

<version>3.2.5</version></dependency>

<!-- cglib 动态代理依赖 stop -->

CGLIB的核心类:

  • net.sf.cglib.proxy.Enhancer – 主要的增强类
  • net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
  • net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:
  •  Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。

实现一个业务类,注意,这个业务类并没有实现任何接口:

public class HelloService {

public HelloService() {

System.out.println("HelloService构造");

}

public void sayHello() {

System.out.println("HelloService:sayHello");

}

net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法

public Object intercept(Object object, java.lang.reflect.Method method,

Object[] args, MethodProxy proxy) throws Throwable;

方法拦截器 实现 MethodInterceptor 接口:

public class HelloServiceInterceptor implements MethodInterceptor{

/**

* sub:cglib生成的代理对象

* method:被代理对象方法

* objects:方法入参

* methodProxy: 代理方法

*/

@Override

public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

System.out.println("======插入前置通知======");

Object object = methodProxy.invokeSuper(sub, objects);

System.out.println("======插入后置通知======");

return object;

}

测试类,生成CGLIB代理对象调用目标方法:

public class CglibTest {

public static void main(String[] args) {

// 通过CGLIB动态代理获取代理对象的过程

Enhancer enhancer = new Enhancer();

// 设置enhancer对象的父类

enhancer.setSuperclass(HelloService.class);

// 设置enhancer的回调对象

enhancer.setCallback(new HelloServiceInterceptor());

// 创建代理对象

HelloService proxy= (HelloService)enhancer.create();

// 通过代理对象调用目标方法

proxy.sayHello();

}

}

Cglib 总结

  • CGlib可以传入接口也可以传入普通的类,接口使用实现的方式,普通类使用会使用继承的方式生成代理类.
  • 由于是继承方式,如果是 static方法,private方法,final方法等描述的方法是不能被代理的
  • 做了方法访问优化,使用建立方法索引的方式避免了传统JDK动态代理需要通过Method方法反射调用.
  • 提供callback 和filter设计,可以灵活地给不同的方法绑定不同的callback。编码更方便灵活。
  • CGLIB会默认代理Object中equals,toString,hashCode,clone等方法。比JDK代理多了clone。

关注公众号:架构进化论,获取第一手互联网开发知识

以上是 性能优于JDK代理,CGLib如何实现动态代理 的全部内容, 来源链接: utcz.com/z/513222.html

回到顶部