【Java】代理机制实现拦截器

Spring框架AOP部分是基于JDK动态代理和CGLIB动态代理实现的,而JDK动态代理(面向接口)是默认的代理模。

为了后期实现Spring框架的简单模拟,首先完成基于这两种代理机制的拦截器。

 

先抛开JDK动态代理和CGLIB动态代理的不同,我们在执行invoke方法时都必须用到三个参数:对象、方法、参数。我们首先假设完成了对三个参数的获取。因为考虑到多个拦截器的存在,我们需要创建一个拦截器链IntercepterChain,并采用间接递归的方式走完所有的拦截器(模拟Spring框架的实现方式)。

在此之前,我们需要先创建一个接口:

package com.chy.StringAOP.core;

import java.lang.reflect.Method;

public interface IIntercepter {
	// 前置拦截!
	boolean before(Object[] args);
	// 后置拦截
	Object after(Object result);
	// 异常处理
	void dealException(Throwable e) throws Throwable;
	// 判断是不是需要拦截的方法
	public boolean isMethod(Method method);
}

下来是通过间接递归实现拦截功能的两个类 :

ProxyInvoker类:

package com.chy.StringAOP.core;

import java.lang.reflect.Method;

public class ProxyInvoker {
	private IntercepterChain intercepterChain;
	
	ProxyInvoker() {
		intercepterChain = new IntercepterChain(this, null);
	}
	
	// 拦截器的添加采用头插的方式
	void addIntercepter(IIntercepter intercepter) {
		IntercepterChain newChain = new IntercepterChain(this, intercepter);
		if (intercepterChain.next == null) {
			intercepterChain.next = newChain;
		} else {
			newChain.next = intercepterChain.next;
			intercepterChain.next = newChain;
		}
	}
	
    // 将拦截器链和截获的参数一同交给doChain()方法执行
    // 拦截器放在链域next中
	Object invoke(IntercepterChain chain, Object object, Method method, Object[] args)
			throws Throwable {
		return chain.doChain(chain.getNext(), object, method, args);
	}
	
	// 得到参数,并带上拦截器链
	Object invoke(Object object, Method method, Object[] args)
			throws Throwable{
		return invoke(intercepterChain, object, method, args);
	}
	
}

 IntercepterChain类:

package com.chy.StringAOP.core;

import java.lang.reflect.Method;

public class IntercepterChain {
	IIntercepter intercepter;
	ProxyInvoker proxyInvoker;
	// 链域
	IntercepterChain next;
	
	// proxyInvoker和实现接口的对象作为参数传进来,并完成初始化
	IntercepterChain(ProxyInvoker proxyInvoker, IIntercepter intercepter) {
		this.proxyInvoker = proxyInvoker;
		this.intercepter = intercepter;
		this.next = null;
	}
	
	IntercepterChain getNext() {
		return next;
	}

	Object doChain(IntercepterChain chain, Object object, Method method, Object[] args) 
			throws Throwable {
		Object result = null;
		if (chain != null) {
			IIntercepter intercepter = chain.intercepter;
				if (intercepter.isMethod(method) 
						&& intercepter.before(args)) {
					try {
						// 间接递归,再次执行带有拦截器链的invoke方法,走完整个链将退出
						result = proxyInvoker.invoke(chain, object, method, args);
						// 每次退出来的执行后置拦截,若无后置拦截,则结果不变
						result = intercepter.after(result);
					} catch (Throwable e) {
						intercepter.dealException(e);
					}
				} else {
					// 若不是需要拦截的方法,或不进行前置拦截,则直接执行
					result = method.invoke(object, args);
				}
		}
		return result;
	}

}

实现了最重要的部分之后,下来处理JDK动态代理和CGLIB动态代理的不同接收方式和整合。

首先是默认的JDK动态代理:

package com.chy.StringAOP.core;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JDKProxy {
	ProxyInvoker chyProxy;
	
	JDKProxy() {
		chyProxy = new ProxyInvoker();
	}
	
	ProxyInvoker getChyProxy() {
		return chyProxy;
	}
	
	// 类类型参数处理
	<T> T getProxy(Class<?> klass) throws Exception {
		Object object = klass.newInstance();
		return getProxy(object, klass.getClassLoader(), klass.getInterfaces());
	}
	
	// 对象类型参数处理
	<T> T getProxy(Object object) {
		Class<?> klass = object.getClass();
		return getProxy(object, klass.getClassLoader(), klass.getInterfaces());
	}
	
	@SuppressWarnings("unchecked")
	private <T> T getProxy(Object object, ClassLoader classLoader, Class<?>[] interfaces) {
		return (T) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				return chyProxy.invoke(object, method, args);
			}
		});
	}
	
}

 CGLIB动态代理的处理:

package com.chy.StringAOP.core;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy {
	ProxyInvoker chyProxy;
	
	CglibProxy() {
		chyProxy = new ProxyInvoker();
	}
	
        <T> T getProxy(Object object) {
		return getProxy(object.getClass(), object);
	}

	<T> T getProxy(Class<?> klass) throws Exception {
		return getProxy(klass, klass.newInstance());
	}
	
	@SuppressWarnings("unchecked")
	private <T> T getProxy(Class<?> klass, Object object) {
		try {
			// 通过参数类型的所有构造器,判断是否有可操作的参数
			Constructor<?> constructor = 
					klass.getDeclaredConstructor(new Class<?>[] {});
			int modifiers = constructor.getModifiers();
			if ((modifiers & Modifier.PRIVATE) != 0) {
				return (T) object;
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(klass);
		enhancer.setCallback(new MethodInterceptor() {
			
			@Override
			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				// TODO 预留操作,从BeanFactory()中获取ProxyInvoker对象
				return chyProxy.invoke(object, method, args);
			}
		});
		
		return (T) enhancer.create();
	}
	
}

整合:

package com.chy.StringAOP.core;

public class ChyProxy {
	public static final int CGLIB_PROXY = 1;
	public static final int JDK_PROXY = 2;

	protected int proxyType;
	
	// 默认为JDK代理
	public ChyProxy() {
		proxyType = JDK_PROXY;
	}
	
	public void setProxyType(int type) {
		this.proxyType = type;
	}
	
	public <T> T getProxy(Class<?> klass) throws Exception {
		if (CGLIB_PROXY == proxyType
				|| klass.getInterfaces().length <= 0) {
			return new CglibProxy().getProxy(klass);
		}
		return new JDKProxy().getProxy(klass);
	}
	
	public <T> T getProxy(Object object) {
		if (CGLIB_PROXY == proxyType
				|| object.getClass().getInterfaces().length <= 0) {
			return new CglibProxy().getProxy(object);
		}
		return new JDKProxy().getProxy(object);
	}
	
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值