AOP源码解析(五)获取代理
来源:互联网 发布:mac os x 10.5正式版 编辑:程序博客网 时间:2024/05/22 14:45
确定了使用哪种代理方式后便可以进行代理的创建了
(1)JDK代理使用示例。
创建业务接口,业务对外提供的接口,包含着业务可以对外提供的功能。
public interface UserService {//目标方法public abstract void add();}
创建业务接口实现类
public class UserServiceImpl implements UserService{public void add() {System.out.println("----------------------add---------------------");}}
创建自定义的InvocationHandler,用于对接口提供的方法进行增强。
public class MyInvocationHandler implements InvocationHandler {//目标对象private Object target;/** * 构造方法 * @param 目标对象 */public MyInvocationHandler(Object target){super();this.target = target;}/** * 执行目标对象的方法 */public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//在目标对象的方法执行之前简单的打印一下System.out.println("----------------------before-------------------");//执行目标对象的方法Object result = method.invoke(target, args);//在目标方法的执行之后简单的打印一下System.out.println("----------------------after-------------------");return result;}/** * 获取目标对象的代理对象 * @return 代理对象 */public Object getProxy(){return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(),this);}}
进行最后测试,验证对于接口的增强是否起到作用。
public class ProxyTest {@Testpublic void testProxy() {//实例化目标对象UserService userService = new UserServiceImpl();//实例化InvocationHandlerMyInvocationHandler invocationHandler = new MyInvocationHandler(userService);//根据目标对象生成代理对象UserService proxy = (UserService)invocationHandler.getProxy();//调用代理对象的方法proxy.add();}}执行结果如下:
----------------------before-----------------------------------------add-------------------------------------------after-------------------
用起来很简单,其实这是基本上就是AOP的一个简单的实现了,在目标对象的方法执行之前和执行之后进行了增强。Spring的AOP实现其实也是用了Proxy的InvocationHandler这两个东西的。
我们再次来回顾一下使用JDK代理的方式,在整个创建的过程中,对于InvocationHandler的创建时最为核心的,在自定义的InvocationHandler中需要重写3个函数。
- 构造函数,将代理的对象传入
- invoke方法,此方法中实现了AOP增强的所有逻辑
- getProxy方法,此方法千篇一律,但是必不可少
那么,我们看看Spring中的JDK代理实现是不是也是这么做的呢?继续之前的跟踪,到达的getProxy。
public Object getProxy(ClassLoader classLoader) { if(logger.isDebugEnabled()) logger.debug((new StringBuilder()).append("Creating JDK dynamic proxy: target source is ").append(advised.getTargetSource()).toString()); Class proxiedInterfaces[] = AopProxyUtils.completeProxiedInterfaces(advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }通过之前的示例我们知道,JDKProxy的使用关键是创建自定义的InvocationHandler,而InvocationHandler中包含了需要覆盖的函数getProxy,而当前的方法正是完成了这个操作。在此确认一下JDKDynamicAopProxy也确实实现了InvocationHandler接口,那么我们就可以推断出,在JdkDynamicAopProxy中一定会有个invoke函数,并且JdkDynamicAopProxy会把AOP的核心逻辑写在其中。查看代码,果然有这样个函数:
public Object invoke(Object proxy, Method method, Object args[]) throws Throwable { Object oldProxy; boolean setProxyContext; TargetSource targetSource; Class targetClass; Object target; oldProxy = null; setProxyContext = false; targetSource = advised.targetSource; targetClass = null; target = null; Object obj; if(equalsDefined || !AopUtils.isEqualsMethod(method)) break MISSING_BLOCK_LABEL_85; obj = Boolean.valueOf(equals(args[0])); if(target != null && !targetSource.isStatic()) targetSource.releaseTarget(target); if(setProxyContext) AopContext.setCurrentProxy(oldProxy); return obj; if(hashCodeDefined || !AopUtils.isHashCodeMethod(method)) break MISSING_BLOCK_LABEL_146; obj = Integer.valueOf(hashCode()); if(target != null && !targetSource.isStatic()) targetSource.releaseTarget(target); if(setProxyContext) AopContext.setCurrentProxy(oldProxy); return obj; //Class类的isAssignableFrom(Class cls)方法:如果调用这个方法的class或接口与参数cls表示的类或接口相同,或者参数与cls表示的类或接口的父类,则返回 //true。形象地:自身类.class.isAssignableFrom(自身类或子类.class)返回true。例: //System.out.println(ArrayList.class.isAssignableFrom(Object.class));//false //System.out.println(Object.class.isAssignableFrom(ArrayList.class));//true if(advised.opaque || !method.getDeclaringClass().isInterface() || !method.getDeclaringClass().isAssignableFrom(org/springframework/aop/framework/Advised)) break MISSING_BLOCK_LABEL_228; obj = AopUtils.invokeJoinpointUsingReflection(advised, method, args); if(target != null && !targetSource.isStatic()) targetSource.releaseTarget(target); if(setProxyContext) AopContext.setCurrentProxy(oldProxy); return obj; Object obj1; if(advised.exposeProxy) { oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } target = targetSource.getTarget(); if(target != null) targetClass = target.getClass(); //获取当前方法的拦截器链 List chain = advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; if(chain.isEmpty()) { //如果没有发现任何拦截器那么直接调用切点方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { //将拦截器封装在ReflectiveMethodInvocation,以便于使用其proceed进行链表用拦截器 MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); //使用拦截器链 retVal = invocation.proceed(); } Class returnType = method.getReturnType(); if(retVal != null && retVal == target && returnType.isInstance(proxy) && !org/springframework/aop/RawTargetAccess.isAssignableFrom(method.getDeclaringClass())) retVal = proxy; else if(retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) throw new AopInvocationException((new StringBuilder()).append("Null return value from advice does not match primitive return type for: ").append(method).toString()); obj1 = retVal; if(target != null && !targetSource.isStatic()) targetSource.releaseTarget(target); if(setProxyContext) AopContext.setCurrentProxy(oldProxy); return obj1; Exception exception; exception; if(target != null && !targetSource.isStatic()) targetSource.releaseTarget(target); if(setProxyContext) AopContext.setCurrentProxy(oldProxy); throw exception; }上面的函数中最主要的工作就是创建了一个拦截器链,并使用ReflectiveMethodInvocation类进行了链的封装,而在ReflectiveMethodInvocation类的proceed方法中实现了拦截器的逐一调用,那么我们继续来研究,在proceed方法中是怎么实现前置增强在目标方法前调用后置增强在目标方法后调用的逻辑呢?
public Object proceed() throws Throwable { //执行完所有增强后执行切点方法 if(currentInterceptorIndex == interceptorsAndDynamicMethodMatchers.size() - 1) return invokeJoinpoint(); //获取下一个要执行的拦截器 Object interceptorOrInterceptionAdvice = interceptorsAndDynamicMethodMatchers.get(++currentInterceptorIndex); if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { //动态匹配 InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice; if(dm.methodMatcher.matches(method, targetClass, arguments)) return dm.interceptor.invoke(this); else //不匹配则不执行拦截器 return proceed(); } else { //普通拦截器,直接调用拦截器,如:MethodBeforeAdviceInterceptor,AspectJAroundAdvice,AdpectJAfterAdvice //将this作为参数传递以保证当前实例中调用链的执行 return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); } }
在proceed方法中,获取代码逻辑并没有我们想象得那么复杂,ReflectiveMethodInvocation中的主要职责是维护了链接调用的计数器,记录着当前调用链的位置,以便链可以有序地进行下去,那么在这个方法中并没有我们之前设想的维护各种增强的顺序,而是将此工作委托给了各个增强器,使各个增强器在内部进行逻辑实现。
0 0
- AOP源码解析(五)获取代理
- AOP源码解析(二)创建AOP代理
- AOP源码解析(一)实现动态代理
- aop源码解析辅助-jdk动态代理
- Spring源代码解析(五):Spring AOP获取Proxy
- Spring源代码解析(五):Spring AOP获取Proxy
- Spring源代码解析(五):Spring AOP获取Proxy
- Spring源代码解析(五):Spring AOP获取Proxy
- Spring源代码解析(五):Spring AOP获取Proxy
- Spring源代码解析(五):Spring AOP获取Proxy
- AOP源码解析(三)增强器的获取
- SSM框架搭建及源码解析--AOP源码解析(五)
- spring 源码探索 -- aop 标签解析和创建代理
- aop源码解析四-代理方法的调用
- iOS推送javaPNS源码解析五,代理管理类
- Spring源码解析之-Aop源码解析(2)
- Vue源码解析(五)
- Spring Aop源码学习--Aop代理AopProxy
- 几种算法的时间和控件复杂度
- 第七章 C控制语句:分支和跳转-C primer plus
- poll
- ORACLE手工备份
- 11月6日 星期天
- AOP源码解析(五)获取代理
- 解决python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX
- 5种常用的服务器编程模型
- ios打包 .ipa
- hdu 5974 A Simple Math Problem
- 系统问题解决笔记
- Django--form生成select标签
- mac 装虚拟机
- Java枚举类型使用