自行编写AOP

为了更好的理解Spring内核,手动编写一个简易版AOP。

至于AOP概念请自行百度,接下来进入正题

先写一个演示用的类NormalClass,给该类添加拦截器,并用该类的代理调用niemalAction方法的过程中拦截。

package com.mec.aop.model;

public class NormalClass {
	public NormalClass() {
	}
	
	public String normalAction(String str) {
		System.out.println(str);
		return str;
	}
}

本例分为3层实现,第一层ProxyFactory,负责产生proxy代理。为了简便,此处仅实现CGLib示例。

package com.mec.aop.core;

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 ProxyFactory {
	private YcProxy ycProxy;
	
	public ProxyFactory() {
	}
	
	public YcProxy getYcProxy() {
		return ycProxy;
	}

	public void setYcProxy(YcProxy ycProxy) {
		this.ycProxy = ycProxy;
	}

	protected <T> T getCGLProxy(Class<?> klass, Object object) {
		T proxy = cglProxy(klass, object);
		ycProxy = new YcProxy();
		ycProxy.setProxy(proxy);
		return proxy;
	}
	
	@SuppressWarnings("unchecked")
	private <T> T cglProxy(Class<?> klass, Object object) {
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(klass);
		enhancer.setCallback(new MethodInterceptor() {
			
			@Override
			public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				return doInvoke(object, method, args);
			}
		});
		
		return (T) enhancer.create();
	}
 	
	@SuppressWarnings("unchecked")
	private <T> T doInvoke(Object object, Method method, Object[] args) {
		Object result = null;
		//置前拦截
		ycProxy.dobefore(method, args);
		try {
			result = method.invoke(object, args);
			//滞后拦截
			ycProxy.doafter(method, result);
		} catch (Throwable e) {
			//异常拦截
			ycProxy.dodealException(method, e);
			e.printStackTrace();
		}
		
		return (T) result;
	}
	
}

第二层YcProxy,负责产生代理类的对象。每一个代理类中包含一个代理,以及与其对应的一套拦截器链。

在该类中主要实现添加和删除拦截器,以及代理的getter和setter方法以备用。还有拦截时调用的三个方法。通过遍历装有拦截器的List,使每一个拦截器均可在方法被调用时起作用。这三个方法的实质是调用的了拦截器类中的抽象方法,此方法留做接口,以便用户将来在拦截时进行操作。

YcProxy类:

/*
 * @auther: yc
 * time: 2018/10/16
 */
package com.mec.aop.core;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class YcProxy {
	private Object proxy;
	private List<YcIntercepter> ycIntercepters;

	public YcProxy() {
		ycIntercepters = new ArrayList<YcIntercepter>();
	}
	
	@SuppressWarnings("unchecked")
	public <T> T getProxy() {
		return (T) proxy;
	}

	public <T> void setProxy(T proxy) {
		this.proxy = proxy;
	}

	public void addIntercepter(YcIntercepter intercepter) throws IntercepterAlreadyExistException {
		if(ycIntercepters.contains(intercepter)) {
			throw new IntercepterAlreadyExistException("拦截器" 
					+ intercepter.getClass().getName() + "已存在");
		}
		ycIntercepters.add(intercepter);
	}
	
	public void removeintercepter(YcIntercepter intercepter) {
		if(!ycIntercepters.contains(intercepter)) {
			return;
		}
		ycIntercepters.remove(intercepter);
	}
	
	public boolean dobefore(Method method, Object[] args) {
		for(YcIntercepter intercepter : ycIntercepters) {
			if(!intercepter.getMethod().equals(method)) {
				continue;
			}

			if(intercepter.before(args).equals(false)) {
				return false;
			}
		}
		
		return true;
	}
	
	public Object doafter(Method method, Object result) {
		for(YcIntercepter intercepter : ycIntercepters) {
			if(!intercepter.getMethod().equals(method)) {
				continue;
			}
			result =  intercepter.after(result);
		}
		
		return result;
	}
	
	public void dodealException(Method method, Throwable e) {
		for(YcIntercepter intercepter : ycIntercepters) {
			if(!intercepter.getMethod().equals(method)) {
				continue;
			}
			intercepter.dealException(e);
		}
	}
	
}

拦截器类:

package com.mec.aop.core;

import java.lang.reflect.Method;

public abstract class YcIntercepter {
	private Method method;
	private Class<?> klass;
	
	public YcIntercepter() {
	}

	public YcIntercepter(Method method, Class<?> klass) {
		super();
		this.method = method;
		this.klass = klass;
	}
	
	public abstract Boolean before(Object[] args);
	public abstract Object after(Object result);
	public abstract void dealException(Throwable e);

	public Method getMethod() {
		return method;
	}

	public void setMethod(Method method) {
		this.method = method;
	}

	public Class<?> getKlass() {
		return klass;
	}

	public void setKlass(Class<?> klass) {
		this.klass = klass;
	}
	
}

为该拦截器类实现一个适配器:

/*
 * @auther: yc
 * time: 2018/10/16
 */
package com.mec.aop.core;

import java.lang.reflect.Method;

public class YcIntercepterAdapter extends YcIntercepter{

	public YcIntercepterAdapter() {
	}
	
	public YcIntercepterAdapter(Method method, Class<?> klass) {
		super(method, klass);
	}

	@Override
	public Boolean before(Object[] args) {
		return true;
	}

	@Override
	public Object after(Object result) {
		return result;
	}

	@Override
	public void dealException(Throwable e) {
	}
	
}

第三层ClassProxyFactory,在该类中编写一个Map,将类名和代理的对象对应起来,并给出用户使用的接口:产生代理和增删拦截器。

ClassProxyFactory类:

/*
 * @auther: yc
 * time: 2018/10/16
 */
package com.mec.aop.core;

import java.util.HashMap;
import java.util.Map;

public class ClassProxyFactory {
	private static final Map<String, YcProxy> map = new HashMap<>();
	
	public <T> T getCGLProxy(Class<?> klass) throws Exception {
		return cglProxy(klass, klass.newInstance());
	}
	
	public <T> T getCGLProxy(Object object) {
		return cglProxy(object.getClass(), object);
	}
	
	private <T> T cglProxy(Class<?> klass, Object object) {
		String ClassName = klass.getName();
		YcProxy ycProxy = map.get(ClassName);
		if(ycProxy != null) {
			return ycProxy.getProxy();
		}
		
		ProxyFactory proxyFactory = new ProxyFactory();
		T proxy = proxyFactory.getCGLProxy(klass, object);
		map.put(ClassName, proxyFactory.getYcProxy());
		
		return proxy;
	}
	
	public void addIntercepter(Class<?> klass, YcIntercepter intercepter) throws IntercepterAlreadyExistException {
		if(!intercepter.getKlass().equals(klass)) {
			return;
		}
		map.get(klass.getName()).addIntercepter(intercepter);
	}
	
	public void removeIntercepter(Class<?> klass, YcIntercepter intercepter) {
		map.get(klass.getName()).removeintercepter(intercepter);
	}
	
}

接下来就来测试一下结果把。在测试之前,需要编写一个类去实现拦截时的三个抽象方法,并作出相应的处理,在此我们简单的输出一下:

实现拦截器的抽象方法的类NormalActionIntercepter:

/*
 * @auther: yc
 * time: 2018/10/16
 */
package com.mec.aop.model;

import java.lang.reflect.Method;

import com.mec.aop.core.YcIntercepterAdapter;

public class NormalActionIntercepter extends YcIntercepterAdapter{

	public NormalActionIntercepter(Method method, Class<?> klass) {
		super(method, klass);
	}
	
	public NormalActionIntercepter() {
	}
	
	@Override
	public Boolean before(Object[] args) {
		for(Object key : args) {
			System.out.println("置前拦截:" + key);
		}
		return true;
	}
	
	@Override
	public Object after(Object result) {
		System.out.println("滞后拦截:" + result);
		return result;
	}
}	

接下来就可以编写测试来看一下结果,其实很简单,创建两个拦截器,通过ClassProxyFactoey类所提供的方法添加,然后通过代理调用normalAction方法即可。

/*
 * @auther: yc
 * time: 2018/10/16
 */
package Test;

import java.lang.reflect.Method;

import com.mec.aop.core.ClassProxyFactory;
import com.mec.aop.model.NormalActionIntercepter;
import com.mec.aop.model.NormalClass;

public class Test {
	public static void main(String[] args) {
		Class<?> klass = NormalClass.class;
		Method method = null;
		try {
			method = klass.getDeclaredMethod("normalAction", new Class<?>[] {String.class});
		} catch (NoSuchMethodException | SecurityException e1) {
			e1.printStackTrace();
		}
		
		NormalActionIntercepter intercepter1 = new NormalActionIntercepter(method, klass);
		NormalActionIntercepter intercepter2 = new NormalActionIntercepter(method, klass);

		ClassProxyFactory classProxyFactory = new ClassProxyFactory();
		
		//生成代理
		try {
			NormalClass normalClass = classProxyFactory.getCGLProxy(klass);
			classProxyFactory.addIntercepter(klass, intercepter1);
			classProxyFactory.addIntercepter(klass, intercepter2);

			normalClass.normalAction("执行normalAction方法");
		} catch (Exception e) {
			e.printStackTrace();
		}

		
	}
}

下面来看一下输出结果:

 两次拦截成功!希望能对你了解AOP有所帮助,欢迎交流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值