cglib动态代理
2019-05-26 本文已影响9人
山东大葱哥
概念及特点
- 使用CGLib实现动态代理,依赖cglib-x.x.x.jar
- 原理是对指定的业务类动态生成一个子类,并覆盖其中业务方法实现代理
- 针对类来实现代理的,完全不受代理类必须实现接口的限制
- CGLib底层采用ASM字节码生成框架,使用字节码技术生成代理类
- 因为采用的是继承,所以不能对final修饰的类进行代理,不能对声明为final的方法进行代理
组成
- 业务实现类 负责实现主要的业务方法(不需要实现接口)
- 实现拦截接口MethodInterceptor,创建动态代理类
案例演示
-
引入cglib
<dependencies> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> </dependencies>
-
业务实现类
public class AccountServiceImpl { public void queryAccount() { System.out.println("查看账户..."); } public void updateAccount() { System.out.println("修改账户..."); } }
-
方法拦截器
public class CglibProxy implements MethodInterceptor { private Object target;//业务类对象,供代理方法中进行真正的业务方法调用 //相当于JDK动态代理中的绑定 public Object getInstance(Object target) { this.target = target; //给业务对象赋值 Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类 enhancer.setSuperclass(this.target.getClass()); //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类) //设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦截 enhancer.setCallback(this); // 创建动态代理类对象并返回 return enhancer.create(); } // 实现回调方法 @Override public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("预处理——————"); proxy.invokeSuper(target, args); //调用业务类(父类中)的方法 System.out.println("调用后操作——————"); return null; } }
- 业务调用
public class CglibProxyApplication { public static void main(String[] args) { AccountServiceImpl accountServiceImpl=new AccountServiceImpl(); CglibProxy cglib=new CglibProxy(); AccountServiceImpl accountServiceProxy=(AccountServiceImpl)cglib.getInstance(accountServiceImpl); accountServiceProxy.queryAccount(); accountServiceProxy.updateAccount(); } }
两种动态代理对比
- 机制区别
- jdk动态代理是通过接口中的方法名,在动态生成的代理类中调用业务实现类的同名方法;利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类;
- cglib动态代理是通过继承业务类,生成的动态代理类是业务类的子类,通过重写业务方法进行代理;cglib底层采用ASM字节码生成框架,使用字节码技术生成代理类;
- 效率对比
- jdk6之前,cglib效率过于jdk反射
- 调用次数较少时,jdk6、jdk7优于cglib
- 调用次数较多时,jdk6、jdk7反射效率低于cglib
- jdk8 动态代理优于cglib效率