cglib是一个强大的高性能的代码生成包,他广泛的被许多的AOP框架使用,例如Spring AOP 和dynaop ,为他们提供方法的拦截(interception),最流行的OR Mapping 工具hibernate也使用CGLIB来代理单端single-ended(多对一和一对一)关联。在这里要说明的是,jdk提供了动态代理功能,但是被代理类必须要有接口,否则是生成不了代理的,但是cglib生成代理时,不需要目标类有接口,因为它借助了asm直接修改class文件的字节码。
就这个动态代理说开来,其实spring的aop不是什么神秘的东西,就是借助动态代理来实现的,并且spring内置了两种代理生成方式,一个就是jdk动态代理API,一个就是cglib。典型的spring组件如声明式的事务管理,通知等。spring的IOC更简单,根据配置文件反射而已。这些东西自己实现并不是什么难事,但是要做到spring那样完善和庞大就是另外一回事了。spring提供的测试框架的mock模块当然也是利用了动态代理的。
下面看看demo吧,具体可自行查阅cglib文档
①:创建一个简单的类,注意该类不能声明为final
QueryDAO.java
package com.cglib.proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @version 1.0
* @history
*/
public class QueryDAO {
@SuppressWarnings("unchecked")
public List executeQuery(String userName) throws Exception{
List list = this.queryForList(userName);
return list;
}
@SuppressWarnings({ "unchecked", "static-access" })
public List queryForList(String userName){
try {
Thread.currentThread().sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
Map<String,String> paramMap = new HashMap<String, String>();
paramMap.put("userName", userName);
List list = new ArrayList();
list.add(paramMap);
return list;
}
}
②:创建性能检测类PerformanceMonitor,需要实现MethodInterceptor(方法拦截)
PerformanceMonitor.java
package com.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;
/**
* @version 1.0
* @history
*/
public class PerformanceMonitor implements MethodInterceptor {
private Object target;
private Enhancer enhander = new Enhancer();
public Object createProxy(Object target){
this.target = target;
enhander.setSuperclass(target.getClass()); //指定父类
enhander.setCallback(this); //回调当前类
return enhander.create(); //创建代理类实例
}
public Object intercept(Object arg0, Method method, Object[] param,
MethodProxy proxyMethod) throws Throwable {
long startTime = System.currentTimeMillis(); //开始时间
Object result = method.invoke(this.target, param); //反射回调方法
long endTime = System.currentTimeMillis(); //结束时间
System.out.println("执行该方法所需时间:" + (endTime-startTime)+"毫秒" );
return result;
}
}
③:Cglib代理类测试效果:
CglibProxyTest.java
package com.cglib.proxy;
public class CglibProxyTest {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
QueryDAO target = new QueryDAO(); //声明被代理类
PerformanceMonitor performance = new PerformanceMonitor();
QueryDAO dao = (QueryDAO)performance.createProxy(target);
dao.executeQuery("admin");
}
}
输入结果
执行该方法所需时间:187毫秒