1 简介
CGLIB(Code Generation Library)是一个开源项目!是一个强大的,高性能,高质量的Code生成类库,它可以在运行期扩展Java类与实现Java接口。Hibernate用它来实现PO(Persistent Object 持久化对象)字节码的动态生成。
2 示例
2.1 MethodInterceptor的使用
原始类:
public class Target
{
public final String say()
{
return "我不想说话";
}
public void doSth()
{
System.out.println("我不想做事");
}
public final void read()
{
System.out.println("不读书");
}
}
代理类:
public class ProxyTarget implements MethodInterceptor
{
@Override
public Object intercept( Object obj, Method method, Object[] args, MethodProxy proxy )
throws Throwable
{
Object result = null;
if ( "say".equals( method.getName() ) )
{
result = obj.getClass().getSimpleName() + " 说 " + proxy.invokeSuper( obj, args );
}
else if ( "doSth".equals( method.getName() ) )
{
System.out.println("干之前……");
result = proxy.invokeSuper( obj, args );
System.out.println("干之后……");
}
else
{
result = proxy.invokeSuper( obj, args );
}
return result;
}
}
测试类:代理工厂:
public static void main( String[] args ) throws InstantiationException, IllegalAccessException
{
Target target = ProxyFactory.getProxy( Target.class, ProxyTarget.class );
System.out.println(target.say());
target.doSth();
target.read();
}
3 附录
3.1 JDK动态代理 vs. CGLIB动态代理
| JDK | CGLIB |
实现方式 | 聚合 | 继承 |
描述 | 针对接口代理 | 针对类代理,生成被代理类的子类,并覆盖其中的方法。 |
优点 | 不关心被代理的类及方法是否final | 不要求代理类有接口 |
缺点 | 要求被代理的类有至少一个接口 | 不能代理final类及不能改写final方法 |
3.2 接口代理 vs. 类代理
接口代理,相当于生成了一个实现了指定接口的代理类;类代理,则是生成了一个指定类的子类。
如果严格按照面向接口编程,那么通常两种生成代理的方式不会有太大差异(如果可以生成的话)。但是,在某些情况下,类似JDK动态代理这种接口代理会面临一些限制。
一种场景是,我们编写一个方法A返回一个代理对象,而这个代理对象被作为参数传入另一个方法B。如果在方法B内,只是将代理对象做为接口对象来使用,那么两种生成代理的方式没有太大的差异。但是,如果试图将代理对象作为某种父类型来使用,那么接口代理将不再适用。