Java的jdk为我们实现动态代理提供了invocationHandler接口,被代理的类必须实现相同的接口。但是很多时候我们拿到的类并没有这样的接口。那么这个时候要实现动态代理就要用到另外一种机制。那就是通过CGLIB来实现动态代理。下面就来看一个最简单的小例子。
首先,简单介绍一下CGLIB实现动态代理的原理。CGLIB通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用。由于是创建的子类,所以就免去了接口的实现,但是这样做也有一些缺陷,对于final修饰的方法无法进行代理。
因为我们要使用CGLIB所以必须先导入相应的包。在这里需要导入cglib.jar以及asm.jar两个包。这两个包随便在网上都能下载。至于怎样导入百度一下有教程,选中工程右键–>Build Path–>Add External Archivels。(注意:以上两个包一定要配套,否则有可能工程会无法正常运行)
下面就正式开始我们的代码编写了。首先我们写一个类,实现一个方法(这里就不再有接口了),在这个方法里面打印一些文字。
public class Helllo {
public void fun()
{
System.out.println("In Hello doing fun()...");
}
}
然后,实现代理类。CGLIB为我们提供了MethodInterceptor接口。创建CGLIBProxy类实现上面的接口,重写intercept()方法,在这里面对调用方法进行拦截。在这个类里还需要创建一个方法用来返回被代理类子类对象。在这里我创建了creatObject()方法
public class CGLIBProxy implements MethodInterceptor{
private Object obj;
public Object createObject(Object target)
{
this.obj = target;
//加载需要创建子类的类
Enhancer hancer = new Enhancer();
hancer.setSuperclass(this.obj.getClass());//设置代理目标
hancer.setCallback(this);//设置回调
hancer.setClassLoader(target.getClass().getClassLoader());
return hancer.create();//返回子类对象
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
Object result = null;
System.out.println("Before....");//调用方法前
result = arg3.invokeSuper(arg0, arg2);
System.out.println("After....");//调用方法后
return result;
}
}
最后,创建一个测试类。
public class CGLIBMain {
public static void main(String[] args)
{
HelloWord hello = new HelloWord();
CGLIBProxy proxy = new CGLIBProxy();
HelloWord helloword = (HelloWord) proxy.createObject(hello);
helloword.sayHello();
}
}
输出结果:
Before...
In Hello doing fun()...
After...