CGLib介绍

CGLIB是一个高性能的代码生成库,用于在运行时扩展Java类和实现Java接口。由于JDK动态代理仅能对实现接口的类进行代理,CGLIB作为补充,可以对未实现接口的类进行代理。CGLIB通过字节码技术生成代理类,比反射效率更高,但不能代理final方法。本文介绍了CGLIB的使用场景、与JDK动态代理的对比,以及CGLIB实现动态代理的源码分析。
摘要由CSDN通过智能技术生成

1. CGLIB介绍

CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,

它可以在运行期扩展Java类与实现Java接口。CGLIB是一个强大的高性能的代码生成包。它广泛的被许多AOP的框架使用,例如Spring AOP为他们提供方法的interception(拦截)。CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类,性能比JDK强。

2. 为什么使用 CGLIB?

CGLIB是一个功能强大,高性能的代码生成它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。

CGLIB代理主要通过对字节码的操作,为对象引入间接级别,以控制对象的访问。我们知道Java中有一个动态代理也是做这个事情的,那我们为什么不直接使用Java动态代理,而要使用CGLIB呢?答案是CGLIB相比于JDK动态代理更加强大JDK动态代理虽然简单易用,但是其有一个致命缺陷是,只能对接口进行代理。如果要代理的类为一个普通类、没有接口,那么Java动态代理就没法使用了。

3. 首先说一下JDK中的动态代理:

JDK中的动态代理是通过反射类Proxy以及InvocationHandler回调接口实现的,但是,JDK中所要进行动态代理的类必须要实现一个接口,也就是说只能对该类所实现接口中定义的方法进行代理,这在实际编程中具有一定的局限性,而且使用反射的效率也并不是很高。

4. 使用CGLib实现动态代理:

使用CGLib实现动态代理,完全不受代理类必须实现接口的限制,而且CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类,比使用Java反射效率要高。唯一需要注意的是,CGLib不能对声明为final的方法进行代理,因为CGLib原理是动态生成被代理类的子类。

5. 使用CGLib实现动态代理

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

package com.jpeony.spring.proxy.cglib;
     
    public class HelloService {
     
        public HelloService() {
            System.out.println("HelloService构造");
        }
     
        /**
         * 该方法不能被子类覆盖,Cglib是无法代理final修饰的方法的
         */
        final public String sayOthers(String name) {
            System.out.println("HelloService:sayOthers>>"+name);
            return null;
        }
     
        public void sayHello() {
            System.out.println("HelloService:sayHello");
        }
    }

自定义MethodInterceptor:

package com.jpeony.spring.proxy.cglib;
 
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
 
import java.lang.reflect.Method;
 
/**
 * 自定义MethodInterceptor
 */
public class MyMethodInterceptor 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代理对象调用目标方法:

package com.jpeony.spring.proxy.cglib;
     
    import net.sf.cglib.core.DebuggingClassWriter;
    import net.sf.cglib.proxy.Enhancer;
     
    public class Client {
        public static void main(String[] args) {
            // 代理类class文件存入本
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CGLIB是一个强大的,高性能的Java代码生成库,它是一个第三方类库,常被用来扩展Java类的功能。它通过在运行时生成字节码,动态地生成代理类来实现对目标对象的扩展,其实现原理与Java JDK自带的动态代理类似,但是CGLIB更加灵活。 CGLIB库的主要特点如下: 1. 高性能:CGLIB使用ASM字节码操作库来生成代理类,速度比使用Java反射要快很多。 2. 灵活性:CGLIB可以对类的任何方法进行代理,不像Java JDK的动态代理只能对接口的方法进行代理。 3. 支持继承代理:CGLIB可以代理普通的Java类,而不仅仅是实现接口的类。 4. 无需接口:CGLIB可以为没有实现任何接口的类创建代理对象。 CGLIB主要是通过在运行时生成目标对象的子类,以此来实现代理的目的。在运行时生成的子类重写了目标对象的方法,并且在重写的方法中添加了代理的逻辑,然后使用这个子类来代替目标对象。 CGLIB的使用需要依赖于cglib-nodep.jar库,这个库可以在CGLIB的官网上下载到。在使用CGLIB时,需要借助Enhancer类来生成代理对象,Enhancer类可以通过设置需要代理的目标类、实现的接口、回调方法等来生成代理对象。 下面是一个简单的使用CGLIB的示例代码: ```java import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibProxy implements MethodInterceptor { private Object target; public Object getInstance(final Object target) { this.target = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("before"); Object result = proxy.invokeSuper(obj, args); System.out.println("after"); return result; } } public class Main { public static void main(String[] args) { CglibProxy cglib = new CglibProxy(); UserDao userDao = (UserDao) cglib.getInstance(new UserDao()); userDao.save(); } } public class UserDao { public void save() { System.out.println("保存用户信息"); } } ``` 在这个示例代码中,CglibProxy类实现了MethodInterceptor接口,并且重写了intercept方法,在intercept方法中添加了代理的逻辑。在Main类中,首先实例化了CglibProxy类,然后通过cglib.getInstance方法生成了UserDao类的代理对象。最后,调用代理对象的save方法时,会先输出"before",然后
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值