cglib可用来在运行时对指定方法进行拦截,简单写了一个用cglib简单的对aop进行了模拟,其中有很多功能没有进行扩展,看过的同学可在基础上添加,首先上配置文件进行解读:
<?xml version="1.0" encoding="UTF-8"?>
<aop>
<aspect name="Worker">
<class method="CountPlus" position="beforeExecution">com.cyj.cglib.Worker</class>
<method name="preStart">com.cyj.cglib.ExtraMethodSet</method>
</aspect>
</aop>
根元素:aop
每个aspect为一个切面,position是切点描述,此处进行化简“beforeExecution”是指在方法执行前进行拦截 ,class节点描述的是被拦截的类和方法
method描述的是添加的增强方法。
即:切面名:Worker 在com.cyj.cglib.Worker类的CountPlus方法执行前执行com.cyj.cglib.ExtraMethodSet类的preStart方法。
生成代理类的工厂如下:
package com.cyj.cglib;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 该功能仅限测试,代理单方法,如需代理多方法可改动AOPDescription及WrapFactory的构造方法
*
* @author Administrator
*
*/
public class WrapFacotry {
private Map<String, AOPDescription> descMap;
private static WrapFacotry wf = new WrapFacotry();
private WrapFacotry() {
this.descMap = new HashMap<String, AOPDescription>();
SAXReader reader = new SAXReader();
Document document = null;
try {
document = reader.read(WrapFacotry.class
.getResourceAsStream("aop.xml"));
Element root = document.getRootElement();
List<Element> AOP = root.selectNodes("aspect");
for (Element aop : AOP) {
String key = aop.attributeValue("name");
Element clazzElement = aop.element("class");
String method = clazzElement.attributeValue("position");
String interceptedMethodName = clazzElement
.attributeValue("method");
String interceptedClassName = clazzElement.getText();
Element methodElement = aop.element("method");
String interceptorClassName = methodElement.getText();
String interceptorMethodName = methodElement
.attributeValue("name");
descMap.put(key, new AOPDescription(method,
interceptedClassName, interceptedMethodName,
interceptorClassName, interceptorMethodName));
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
public static WrapFacotry getFactory() {
return wf;
}
public Object getInstance(String name) throws ClassNotFoundException {
final AOPDescription desc = descMap.get(name);
if (desc != null) {
String targetName = desc.getInterceptedClassName();
Enhancer en = new Enhancer();
final Class targetClass = Class.forName(targetName);
en.setSuperclass(targetClass);
en.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1,
Object[] arg2, MethodProxy arg3) throws Throwable {
if (arg1.getName().equals(desc.getInterceptedMethodName())) {
if (desc.getMethod().equals("beforeExecution")) {
Class clazz = Class.forName(desc
.getInterceptorClassName());
Object interceptor = clazz.newInstance();
// 可在配置文件中定义参数类型
Method interceptorMethod = clazz.getDeclaredMethod(
desc.getInterceptorMethodName(), null);
interceptorMethod.invoke(interceptor, null);
}
arg1.invoke(targetClass.newInstance(), arg2);
if (desc.getMethod().equals("postExecution")) {
Class clazz = Class.forName(desc
.getInterceptorClassName());
Object interceptor = clazz.newInstance();
// 可在配置文件中定义参数类型
Method interceptorMethod = clazz.getDeclaredMethod(
desc.getInterceptorMethodName(), null);
interceptorMethod.invoke(interceptor, null);
}
}
return null;
}
});
return en.create();
}
throw new ClassNotFoundException();
}
@Test
public void t() {
}
}
class AOPDescription {
private String method;
private String interceptedClassName;
private String interceptedMethodName;
private String interceptorClassName;
private String interceptorMethodName;
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getInterceptedClassName() {
return interceptedClassName;
}
public void setInterceptedClassName(String interceptedClassName) {
this.interceptedClassName = interceptedClassName;
}
public String getInterceptedMethodName() {
return interceptedMethodName;
}
public void setInterceptedMethodName(String interceptedMethodName) {
this.interceptedMethodName = interceptedMethodName;
}
public String getInterceptorClassName() {
return interceptorClassName;
}
public void setInterceptorClassName(String interceptorClassName) {
this.interceptorClassName = interceptorClassName;
}
public String getInterceptorMethodName() {
return interceptorMethodName;
}
public void setInterceptorMethodName(String interceptorMethodName) {
this.interceptorMethodName = interceptorMethodName;
}
public AOPDescription(String method, String interceptedClassName,
String interceptedMethodName, String interceptorClassName,
String interceptorMethodName) {
super();
this.method = method;
this.interceptedClassName = interceptedClassName;
this.interceptedMethodName = interceptedMethodName;
this.interceptorClassName = interceptorClassName;
this.interceptorMethodName = interceptorMethodName;
}
}
其中AOPDescription是pojo仅仅是保存对切面的描述,时间原因这个工厂只能添加一个增强方法,后续可以把method放入一个list中进行执行,有兴趣的可以自行添加
方法的参数没有定义,可以在配置文件中添加类似节点,有空再说。。。
此处每次调用一个getInstance方法就会返回一个由cglib产生的类,无聊的可以建一个静态的map结构,每产生一个放入map中,第二次就可以直接从map中拿,算是一个优化吧。。。
下面上实体类,一个是被增强类,一个是增强类:
package com.cyj.cglib;
public class Worker {
private int count;
public Worker(){
this.count = 0;
}
public int CountPlus(){
System.out.println("CountPlus");
return ++count;
}
public int CountMinus(){
System.out.println("CountMinus");
return --count;
}
}
package com.cyj.cglib;
public class ExtraMethodSet {
public void printCurrentTimeMillis(){
System.out.println(System.currentTimeMillis());
}
public void preStart(){
System.out.println("Method Start");
}
public void postEnd(){
System.out.println("Method Over");
}
}
测试类:
package com.cyj.cglib.test;
import org.junit.Test;
import com.cyj.cglib.Worker;
import com.cyj.cglib.WrapFacotry;
public class TestAOP {
@Test
public void t() throws ClassNotFoundException{
WrapFacotry fa = WrapFacotry.getFactory();
Worker worker = (Worker)fa.getInstance("Worker");
worker.CountPlus();
}
}
好,目前为止,这个模拟aop的代码结束,大家扣脚的时间可以对这段模拟代码进行一些优化。
坚信!未来属于猥琐的扣脚大叔们!