目前的Java开发包中包含了对动态代理的支持,但是其实现只支持对接口的的实现。即如果想对一个类进行动态代理,那么这个类首先要继承了某个接口,否则就无法对其进行代理。
CGLIB就可以对一个普通java类进行代理,不需要其实现任何接口。CBLIB的实现采用非常底层的字节码技术,为一个类动态生成一个子类,并在子类中覆盖其父类所有的非final的方法,对其进行拦截,以实现动态代理的效果,是对JDK动态代理的一个很好的补充。
我写了个小例子,HelloWorld类为业务方法类(没有实现任何接口),其中包括一个有返回值和无返回值的两个方法,CglibProxy为动态代理类,在这个类中可以实现对HelloWorld类方法的拦截,可以把诸如权限校验、记录日志这样的横切性问题在这里进行处理。
业务实现类:
package com.why.cglib.proxy;
/**
* 业务实现类
* @author why
*
*/
public class HelloWorld{
public void sayHello() {
System.out.println("执行了 sayHello()");
}
public String sayHelloWithReturnValue() {
String str = "HelloWorld!";
System.out.println("执行了 sayHelloWithReturnValue()");
return str;
}
}
动态代理类:
package com.why.cglib.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 动态代理类
* @author why
*
*/
public class CglibProxy implements MethodInterceptor{
private Object targetObject;//要代理的目标对象
public Object newProxy(Object targetObject) {
this.targetObject = targetObject ;
Enhancer enhancer = new Enhancer();//该类用于生成代理对象
enhancer.setSuperclass(this.targetObject.getClass());//设置父类
enhancer.setCallback(this);//设置回调对象为本身
return enhancer.create();//通过字节码技术动态创建子类实例
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object result = null;;
doBefore();
try{
result = methodProxy.invokeSuper(proxy, args);//调用原始对象的方法
doAfter();
}catch (Exception e) {
e.printStackTrace();
doWhenException();
}finally{
doFinally();
}
return result;
}
private void doBefore() {
System.out.println("before method invoke!");
}
private void doAfter() {
System.out.println("after method invoke!");
}
private void doWhenException() {
System.out.println("WhenException method invoke!");
}
private void doFinally() {
System.out.println("Finally method invoke!");
}
}
测试类:
package com.why.cglib.proxy;
public class Test {
/**
* CGLIB 动态代理
*
* @param args
*/
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
HelloWorld proxy = (HelloWorld)cglibProxy.newProxy(new HelloWorld());
proxy.sayHello();
System.out.println("\n---------------------------------\n");
String str = proxy.sayHelloWithReturnValue();
System.out.println("str = " + str);
}
}