学科分类
目录
SSM框架

CGLIB代理

JDK动态代理的使用非常简单,但它还有一定的局限性——使用动态代理的对象必须实现一个或多个接口。如果要对没有实现接口的类进行代理,那么可以使用CGLIB代理。

CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类进行增强。在Spring的核心包中已经集成了CGLIB所需要的包,所以开发中不需要另外导入JAR包。

接下来,通过一个案例来演示CGLIB代理的实现过程,具体步骤如下。

(1)在src目录下,创建一个com.itheima.cglib包,在包中创建一个目标类UserDao,UserDao不需要实现任何接口,只需定义一个添加用户的方法和一个删除用户的方法,如文件1所示。

文件1 UserDao.java

 1    package com.itheima.cglib;
 2    //目标类
 3    public class UserDao {
 4        public void addUser() {
 5            System.out.println("添加用户");
 6        }
 7        public void deleteUser() {
 8            System.out.println("删除用户");
 9        }
 10    }

(2)在com.itheima.cglib包中,创建代理类CglibProxy,该代理类需要实现MethodInterceptor接口,并实现接口中的intercept()方法,如文件2所示。

文件2 CglibProxy.java

 1    package com.itheima.cglib;
 2    import java.lang.reflect.Method;
 3    import org.springframework.cglib.proxy.Enhancer;
 4    import org.springframework.cglib.proxy.MethodInterceptor;
 5    import org.springframework.cglib.proxy.MethodProxy;
 6    import com.itheima.aspect.MyAspect;
 7    // 代理类
 8    public class CglibProxy implements MethodInterceptor{
 9        // 代理方法
 10        public  Object createProxy(Object target) {
 11            // 创建一个动态类对象
 12            Enhancer enhancer = new Enhancer();
 13            // 确定需要增强的类,设置其父类
 14            enhancer.setSuperclass(target.getClass());
 15            // 添加回调函数
 16            enhancer.setCallback(this);
 17            // 返回创建的代理类
 18            return enhancer.create();
 19        }
 20        /**
 21         * proxy CGlib根据指定父类生成的代理对象
 22         * method 拦截的方法
 23         * args 拦截方法的参数数组
 24         * methodProxy 方法的代理对象,用于执行父类的方法 
 25         */
 26        @Override
 27        public Object intercept(Object proxy, Method method, Object[] args, 
 28                                     MethodProxy methodProxy) throws Throwable {
 29             // 创建切面类对象
 30            MyAspect myAspect = new MyAspect();
 31            // 前增强
 32            myAspect.check_Permissions();
 33            // 目标方法执行
 34            Object obj = methodProxy.invokeSuper(proxy, args);
 35            // 后增强
 36            myAspect.log();    
 37            return obj;
 38        }
 39    }

在文件2的代理方法中,首先创建了一个动态类对象Enhancer,它是CGLIB的核心类;然后调用了Enhancer类的setSuperclass()方法来确定目标对象;接下来调用了setCallback()方法添加回调函数,其中的this代表的就是代理类CglibProxy本身;最后通过return语句将创建的代理类对象返回。intercept()方法会在程序执行目标方法时被调用,方法运行时将会执行切面类中的增强方法。

(3)在com.itheima.cglib包中,创建测试类CglibTest。在该类的main()方法中首先创建代理对象和目标对象,然后从代理对象中获得增强后的目标对象,最后调用对象的添加和删除方法,如文件3所示。

文件3 CglibTest.java

 1    package com.itheima.cglib;
 2    // 测试类
 3    public class CglibTest {
 4        public static void main(String[] args) {
 5            // 创建代理对象
 6            CglibProxy cglibProxy = new CglibProxy();
 7                 // 创建目标对象
 8            UserDao userDao = new UserDao();
 9             // 获取增强后的目标对象
 10            UserDao userDao1 = (UserDao)cglibProxy.createProxy(userDao);
 11            // 执行方法
 12            userDao1.addUser();
 13            userDao1.deleteUser();
 14        }
 15    }

执行程序后,控制台的输出结果如图1所示。

图1 运行结果

从图1可以看出,目标类UserDao中的方法被成功调用并增强了。这种没有实现接口的代理方式,就是CGLIB代理。

点击此处
隐藏目录