使用CGLIB动态代理

使用CGLIB动态代理

http://www.gwdang.com

http://www.gwdang.com/app/extension

Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类。使用CGLIB即使被代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:

使用CGLIB需要导入以下两个jar文件:

asm.jar – CGLIB的底层实现。

cglib.jar  CGLIB的核心jar包。

CGLIB的核心类:

net.sf.cglib.proxy.Enhancer  主要的增强类

net.sf.cglib.proxy.MethodInterceptor  主要的方法拦截类,它是Callback接口的子接口,需要用户实现

net.sf.cglib.proxy.MethodProxy  JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用,如使用:

Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。

费话少说,上代码:

1、使用CGLIB的代理:

以下测试代理一个没有实现任何接口的Person类:

@Test

public void testProxy1() throws Exception {

final Person p1 = new Person();   //Person类没有实现任何接口

Enhancer en = new Enhancer();    //声明增加类实例

en.setSuperclass(Person.class);   //设置被代理类字节码,CGLIB根据字节码生成被代理类的子类

en.setCallback(new MethodInterceptor() {    //设置回调函数,即一个方法拦截

public Object intercept(Object target, Method method,

Object[] args, MethodProxy proxy) throws Throwable {

Object o = method.invoke(p1,args);    //注意参数p1,仍然为外部声明的源对象,且Method为JDK的Method反射

System.err.println("After...");

return o;

}

});

Person p = (Person) en.create();    //通过create方法返回Person类的代理

System.err.println(p.getClass());//被代理的对象

p.sayHi("Hello");

}

2、以下测试代理一个拥有接口的类:

IAnimal是接口,Dog是实现类,具体代码如下:

@Test

public void testProxy2() throws Exception {

final Dog dog = new Dog(); //声明被代理对象

Enhancer en = new Enhancer(); //声明CGLIB增强类

en.setSuperclass(IAnimal.class); //设置接口类,也可以设置成dog实现类,会影响create返回的对象

en.setCallback(new MethodInterceptor() {

public Object intercept(Object target, Method method,

Object[] args, MethodProxy proxy) throws Throwable {

System.err.println("Before...");

Object o = method.invoke(dog, args);

System.err.println("After...");

return o;

}

});

//Dog dog2 = (Dog) en.create();//必须转型为接口,否则抛出ClassCastException

IAnimal dog2 = (IAnimal)en.create();

dog2.eat();

}

说明:

由于上例中,设置了en.setSuperclass(IAnimal.class),所以en.create()方法,返回的对象,必须要转换成IAnimal接口。如果转换成Dog则会抛出ClassCastException。

3、将CGLIB再做一个简单的包装:

class CglibProxy implements MethodInterceptor{

private Object srcTarget;

private CglibProxy(Object o){

this.srcTarget = o;

}

@SuppressWarnings("unchecked")

public static <T>T proxyTarget(T t){

Enhancer en = new Enhancer();

en.setSuperclass(t.getClass());

en.setCallback(new CglibProxy(t));

T tt = (T) en.create();

return tt;

}

@Override

public Object intercept(Object obj, Method method, Object[] args,

MethodProxy proxy) throws Throwable {

System.err.println("拦截前...");

Object o = method.invoke(srcTarget, args);

System.err.println("拦截后....");

return o;

}

}

包装以后的调用代码如下,主要是快速的实现获取被代理类:

Person p = CglibProxy.proxyTarget(new Person());

p.sayHi("HJello");

IAnimal dog = CglibProxy.proxyTarget(new Dog());

dog.eat();

4、使用静态方法代理一个没有接口的对象

以下代码,包含在一个测试方法或是main方法中运行:

final Person src = new Person();

    //直接使用静态方法代理一个对象

Person p = (Person) Enhancer.create(Person.class,new MethodInterceptor(){

public Object intercept(Object proxyedObj, Method method, Object[] args,

MethodProxy proxy) throws Throwable {

System.err.println("Hello");

//使用原生的方法调用,注意里面的src

//Object oo = method.invoke(srcargs);

//使用MethodProxy调用父类的代码,同样有效

Object oo = proxy.invokeSuper(proxyedObj, args);

return oo;

}

});

System.err.println(p.getClass());

p.abc();

你可能感兴趣的:(使用CGLIB动态代理)