cglib简单模拟aop

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的代码结束,大家扣脚的时间可以对这段模拟代码进行一些优化。

坚信!未来属于猥琐的扣脚大叔们!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值