CGLib 动态代理cglib动态代理原理
CGLib全称是Code Generation Library(https:///cglib),是一个第三方开源的代码生成包,功能很强大,性能很优越,许多开源框架如Spring、Hibernate、EasyMock都使用了这个包来实现动态代理。
Java提供的动态代理是通过实现业务接口来生成一个新的代理类,所以需要定义接口,没有业务接口就没办法生成代理类;CGLib动态代理可以解决这个问题,它不需要业务接口,它直接以委托类(目标类)为父类生成一个增强的子类(代理类),所以这种方式不需要接口,但有一个前提是目标类不能被final修饰,即目标类必须是可继承的。
除了动态生成代理类这能力之外,CGLib还能干很多事情,比如过滤目标类的某些方法不被代理等;另外在最新版本的CGLib库中也提供InvocationHandler接口和Proxy类,即CGLib同时提供了与Java动态代理一样的功能。
MethodInterceptor接口:调用业务方法可以使用Method参数或者MethodProxy参数,建议使用MethodProxy参数,性能比较快。
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;简单代码示例:
package .delegate; public class SalaryService { public void raise(){ System.out.println("raise someone's salary"); } public void query(){ System.out.println("query someone's salary"); } } package .delegate; import java.lang.reflect.Method; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.CallbackFilter; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.NoOp; public class CglibDynamicProxy implements MethodInterceptor { public Enhancer enhancer = new Enhancer(); private String name; public CglibDynamicProxy(String name) { = name; } public Object newProxyInstance(Class cls) { enhancer.setSuperclass(cls); //设置回调实例 enhancer.setCallbacks(new Callback[]{this, NoOp.INSTANCE}); //设置回调过滤器 enhancer.setCallbackFilter(new CallbackFilter(){ public int accept(Method method) { return "query".equalsIgnoreCase(method.getName()) ? 1 : 0; } }); return enhancer.create(); } public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { if (!"HR".equals(name)) { System.out.println(name + ", 没有权限进行此操作!"); return null; } Object result = methodProxy.invokeSuper(object, args); return result; } } package .delegate; import net.sf.cglib.proxy.Proxy; public class CGLibProxyTest { public static void main(String[] args) { test("HR"); test("Steve"); } private static void test(String name) { SalaryService s1 = getSalaryService(name); s1.raise(); s1.query(); } private static SalaryService getSalaryService(String name) { CglibDynamicProxy proxy = new CglibDynamicProxy(name); return (SalaryService) proxy.newProxyInstance(SalaryService.class); } }