什么是Cglib
Cglib是一个强大的,高性能,高质量的代码生成类库。它可以在运行期扩展JAVA类与实现JAVA接口。其底层实现是通过ASM字节码处理框架来转换字节码并生成新的类。大部分功能实际上是ASM所提供的,Cglib只是封装了ASM,简化了ASM操作,实现了运行期生成新的class。
Cglib的原理
运行时动态的生成一个被代理类的子类(通过ASM字节码处理框架实现),子类重写了被代理类中所有非final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势植入横切逻辑。
Cglib优缺点
优点:JDK动态代理要求被代理的类必须实现接口,当需要代理的类没有实现接口时Cglib代理是一个很好的选择。另一个优点是Cglib动态代理比使用java反射的JDK动态代理要快(Cglib的FastClass机制,解析参考http://www.cnblogs.com/cruze/p/3865180.html#lable3)
缺点:对于被代理类中的final方法,无法进行代理,因为子类中无法重写final函数
Cglib类库
net.sf.cglib.core:底层字节码处理类,他们大部分与ASM有关系。
net.sf.cglib.transform:编译期或运行期类和类文件的转换
net.sf.cglib.proxy:实现创建代理和方法拦截器的类
net.sf.cglib.reflect:实现快速反射和C#风格代理的类
net.sf.cglib.util:集合排序等工具类
net.sf.cglib.beans:JavaBean相关的工具类
最主要的一个接口CallBack接口,即回调接口,下面的拦截器、过滤器、延迟加载都继承于它,结构图如下:
Cglib的拦截器和过滤器
拦截器:实现MethodInterceptor接口的类,在intercept方法中实现对代理目标类的方法拦截。但同时Cglib为简化和提高性能提供了一些专门的回调类型如FixedValue(可以在实现的方法loadObject中指定返回固定值,而不调用目标类函数)、NoOp(把对回调方法的调用直接委派到这个方法的父类,即不进行拦截)
过滤器:实现CallbackFilter接口的类,通过accept方法返回一个下标值,用于指定调用哪个拦截器进行拦截处理
/** * @author longe * 被代理类 */ public class TDao { public void create() { System.out.println("create() is running !"); } public void query() { System.out.println("query() is running !"); } public void update() { System.out.println("update() is running !"); } public void delete() { System.out.println("delete() is running !"); } } /** * @author longe * 过滤器 */ public class TDaoCglibFilter implements CallbackFilter { public final static int NO_RESTRICTION = 0; public final static int RESTRICTION_CREATE = 1; /* (non-Javadoc) * 根据调用的方法返回使用的callbacks下标 */ @Override public int accept(Method method) { if(method.getName().startsWith("create")){ return RESTRICTION_CREATE; } return NO_RESTRICTION; } } /** * @author longe * 拦截器 */ public class TDaoCglibProxy implements MethodInterceptor { private String name; private Object objT; public TDaoCglibProxy(String name) { this.name = name; } public TDaoCglibProxy(Object obj,String name) { this.name = name; this.objT = obj; } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if(!name.equals("张三")){ System.out.println("没有权限!"); return null; } // return method.invoke(objT, args); //通过反射进行调用 return proxy.invokeSuper(obj, args); //使用Cglib代理调用 } public static void main(String[] args) { Enhancer en = new Enhancer(); en.setSuperclass(TDao.class); TDaoCglibProxy callBack = new TDaoCglibProxy("张三1"); // 指定两个callback,通过callBackFilter返回的下标值控制调用使用那一个callback处理 en.setCallbacks(new Callback[] { NoOp.INSTANCE, callBack }); // 方法过滤器,根据过滤器返回不同的值回调对应下标的Callback方法 en.setCallbackFilter(new TDaoCglibFilter()); TDao dao = (TDao) en.create(); dao.create(); dao.query(); dao.update(); dao.delete(); } }