AOP的模拟实现

本文详细介绍了Spring框架中的AOP(面向切面编程)和IOC(控制反转)技术,重点讲解了AOP的概念及其如何通过动态代理实现。文中提供了一个使用JDK动态代理模拟AOP的简单示例,包括目标类、代理类和拦截器链的实现,展示了如何在不修改源代码的情况下,通过拦截器在方法调用前后插入额外逻辑。此外,还给出了一个具体的拦截器实现和测试案例,展示AOP在实际应用中的工作流程。
摘要由CSDN通过智能技术生成

AOP和IOC是Spring框架的两个核心技术。

AOP:面向切面编程(Aspect Oriented Programming),通过预编译方式和运行期动态代理来实现程序功能的统一与扩展的技术。
AOP可以对业务逻辑部分进行隔离,从而使业务逻辑耦合降低,提高代码复用和开发效率。
是基于动态代理实现的,如果目标对象实现了接口,就用JDK动态代理,未实现接口就用CGLIB动态代理。
通过AOP技术,在不修改源代码的情况下,为程序添加了新的功能,是对程序的非侵入式扩展。

AOP的简单模拟实现:
为了在目标方法前后执行新的方法,且不对源代码进行修改,所以要用动态代理,让代理去执行目标方法,然后在执行方法前进行前置拦截,在执行方法后进行后置拦截。

1.目标方法所在类:

//接口
public interface IDoSomething {
	String doSomething(String str);
	void doOther(int num);
}

//实现接口的类:
public class DoSomething implements IDoSomething {

	public DoSomething() {
	}

	@Override
	public String doSomething(String str) {
		return "(" + str + ")";
	}

	@Override
	public void doOther(int num) {
		System.out.println("num:" + num);
	}

}

2.JDK动态代理:

public class JDKProxy {
	private static IntercepterChain chain = new IntercepterChain();
	static IntercepterChain getIntercepterChain() {
		return chain;
	}

	@SuppressWarnings("unchecked")	public <T> T getProxy(Object object) {
		Class<?> klass = object.getClass();		
		ClassLoader classLoader = klass.getClassLoader();		
		Class<?>[] interfaces = klass.getInterfaces();			
		
		return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {			
			@Override			
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {			
				Object result = null;				
				// 前置拦截				
				if (JDKProxy.chain.dobefore(method,args)) {					
					try {	
					//目标方法				
						result = method.invoke(object, args);					
						}catch (Throwable e) {										
							throw e;				
						}				
					// 后置拦截					
					result = JDKProxy.chain.doAfter(method,result);			
					return result;				
					}					
				return null;			
				}		
			});	
		}		
	
	public <T> T getProxy(Class<?> klass) {		
		try {			
			Object object = klass.newInstance();		
			return getProxy(object);		
			} catch (InstantiationException e) {			
				e.printStackTrace();		
			} catch (IllegalAccessException e) {		
					e.printStackTrace();	
			}				
		return null;
	}
}

拦截器链:

public class IntercepterChain {
	private IIntercepter intercepter;//数据域
	private IntercepterChain chain;//链域
	private String targetMethod;//拦截目标

	//不断追加拦截器
	public static void addIntercepter(String targetMethod, IIntercepter 						intercepter) {	JDKProxy.getIntercepterChain().setIntercepter(targetMethod,intercepter);
	}
	
	//链表的追加原理:数据域是空则直接设置,不为空则创建一个新的结点,然后再把数据设置进去,并且让前一个链域指向新的结点。
	public void setIntercepter(String targetMethod, IIntercepter intercepter) {
		if(this.intercepter == null) {
			this.intercepter = intercepter;
			this.targetMethod = targetMethod.toString().replace("*", ".*");
			
			return;
		}
		
		if(this.chain == null) {
			IntercepterChain intercepterChain = new IntercepterChain();
			this.chain = intercepterChain;
			intercepterChain.setIntercepter(targetMethod, intercepter);
			return;
		}
		
		this.chain.setIntercepter(targetMethod, intercepter);
		
	}
	
	//让所形成的链表,
	boolean dobefore(Method method, Object[] args) {
		if(this.chain != null && !this.chain.dobefore(method, args)) {
			return false;
		}
		if(this.intercepter != null) {
			String methodStr = method.toString();
			if(Pattern.matches(this.targetMethod, methodStr)) {
				return this.intercepter.before(args);
			}
			return true;
		}
		return true;
	}

	Object doAfter(Method method, Object result) {
		if(this.intercepter != null) {
			String methodStr = method.toString();
			if(Pattern.matches(this.targetMethod, methodStr)) {
				result = this.intercepter.after(result);
			}
			return result;
		}
		
		if(this.chain != null) {
			result = this.chain.doAfter(method, result);
		}
		return result;
	}
}

获取代理对象,并且在dobefore()内部采用正则表达式来有选择的进行拦截处理。
当dobefore()方法返回值为true时,则可以正常执行目标方法,否则不执行。

拦截器所要实现的接口:

public interface IIntercepter {
	boolean before(Object[] args);//前置拦截:如果返回值为false则为不允许执行下面的方法
	Object after(Object result);//后置拦截主要针对于方法执行的结果
}

测试:

首先实现一个拦截器:

public class IntercepterOne implements IIntercepter {

	public IntercepterOne() {
	}

	@Override
	public boolean before(Object[] args) {
		String arg0 = (String)args[0];
		arg0 = "##" + arg0 + "##";
		args[0] = arg0;
		
		return true;
	}
	
	@Override
	public Object after(Object result) {
		return "--" + result + "--";
	}

}

测试类:

public static void main(String[] args) {
		String matcher = "*com.mec.aop.test.*.doSomething(*)";//拦截目标
		IntercepterChain.addIntercepter(matcher,new IntercepterOne());
		
		DoSomething ds = new DoSomething();
		JDKProxy proxy = new JDKProxy();
		
		IDoSomething iProxy = proxy.getProxy(ds);
		String str = iProxy.doSomething("坚果");
		System.out.println(str);
		iProxy.doOther(20);
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值