由于JDK所提供的动态代理只能为接口创建动态代理,不能直接通过类来进行代理,所以这在没有定义接口的情况下是不实用的,这个时候就需要使用cglib来实现动态代理。
通过实例来看一下cglib的动态代理,其中只涉及到了3个类,一个是业务类,一个是cglib代理类,一个是测试类:
业务类StudentServiceImpl:
package cn.qing.cglib.proxy;
public class StudentServiceImpl {
public String findStudent(String stuName) {
System.out.println("findStudent method....");
return "name:\t"+stuName;
}
public int findStudentNum() {
System.out.println("findStudentNum method ...");
return 20;
}
}
cglib代理类:
package cn.qing.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;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
/**
* 使用Cglib返回一个代理对象
* @param clazz
* @return
*/
public Object getProxy(Class clazz)
{
//将需要代理的类设置为superclass
enhancer.setSuperclass(clazz);
//设置回调方法
enhancer.setCallback(this);
//创建一个代理
return enhancer.create();
}
public Object intercept(Object object, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
System.out.println("befor execute method:"+method.getName());
System.out.println("可以在这里添加一些前置操作....");
//通过代理类调用父类中的方法
Object obj = proxy.invokeSuper(object, args);
System.out.println("after execute method:"+method.getName());
System.out.println("可以在这里添加一些后置操作....");
return obj;
}
}
测试类:
package cn.qing.cglib.proxy;
public class TestCglibProxy {
/**
* @param args
*/
public static void main(String[] args) {
TestCglibProxy tcp = new TestCglibProxy();
StudentServiceImpl service = tcp.getIStudentServiceInstance();
System.out.println("getClass:"+service.getClass());
System.out.println("super class:"+service.getClass().getSuperclass());
System.out.println("*****************************");
service.findStudent("xiaoming");
System.out.println("*****************************");
service.findStudentNum();
}
/**
* 通过cglib来获得实例代理对象
* @return
*/
public StudentServiceImpl getIStudentServiceInstance()
{
CglibProxy cp = new CglibProxy();
StudentServiceImpl service = (StudentServiceImpl)cp.getProxy(StudentServiceImpl.class);
return service;
}
}
输出结果:
getClass:class cn.qing.cglib.proxy.StudentServiceImpl$$EnhancerByCGLIB$$1640169f
super class:class cn.qing.cglib.proxy.StudentServiceImpl
*****************************
befor execute method:findStudent
可以在这里添加一些前置操作....
findStudent method....
after execute method:findStudent
可以在这里添加一些后置操作....
*****************************
befor execute method:findStudentNum
可以在这里添加一些前置操作....
findStudentNum method ...
after execute method:findStudentNum
可以在这里添加一些后置操作....
由输出结果可以看出,第一个getclass()方法得到的确实是cglib创建的代理对象,通过调用getSuperclass()才获取到真正被代理的对象类,在方法执行的时候,也同样执行了在代理中添加的前置或后置代码。可以看到,cglib在创建代理的时候,直接使用了类,而并没有要求类实现接口,当然如果代理类实现了某些接口也是可以正常被代理的。而且cglib还提供了很多动态代理的功能点,这些是JDK动态代理所没有的。同时cglib也被使用在Spring框架中用来实现其AOP功能。
ps:在单独使用cglib时除了需要引入cglib包以外,还需要引入asm.jar包,因为cglib底层实现是通过ASM类实现的(ASM是小巧轻便的 Java 字节码操控框架 ,它能方便地生成和改造 Java 代码。)。