CGLib全称是Code Generation Library(https://github.com/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 com.stevex.app.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 com.stevex.app.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) {
		this.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 com.stevex.app.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);
	}

}