龙空技术网

Spring AOP代理对象运行原理解析

记录生活的小熊 685

前言:

目前各位老铁们对“aop代理机制”大体比较看重,大家都想要知道一些“aop代理机制”的相关知识。那么小编也在网络上汇集了一些关于“aop代理机制””的相关知识,希望小伙伴们能喜欢,小伙伴们快快来了解一下吧!

引言

Spring的AOP 主要是由切面和代理对象两块内容实现的,切面以及代理对象的初始化原理已经在Spring AOP 实现原理解析 分析过了,现在就从源码方面来分析一下代理对象在spring中如何工作的[奋斗]

代理对象执行机制

下面我们直接通过JdkDynamicAopProxy源码来对代理对象的运行机制进行解析,直接上源码:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {		Object oldProxy = null;		boolean setProxyContext = false;		TargetSource targetSource = this.advised.targetSource;		Object target = null;		try {      //equal方法不进行特殊处理,直接调用equals方法			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {				return equals(args[0]);			}       //hashCode方法不进行特殊处理,直接调用hashCode方法			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {				return hashCode();			}     //还有一些其他不需要代理的方法,无关主流程,省略			Object retVal;     //判断@EnableAspectJAutoProxy是否配置exposeProxy = true			if (this.advised.exposeProxy) {				oldProxy = AopContext.setCurrentProxy(proxy);				setProxyContext = true;			}			//			target = targetSource.getTarget();			Class<?> targetClass = (target != null ? target.getClass() : null);     //从缓存中获取增强器,并将增强器转化为方法拦截器链			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);		//因为我们配置了切面,所以拦截器链不为空,内部省略			if (chain.isEmpty()) {			}			else {				// 创建拦截器链方法调用器,这个调用器就充分的展示了Aop使用了所谓的责任链模式				MethodInvocation invocation =						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);				/* 这里就是循环的调用拦截器链中各增强器的方法,aop的切面代理功能就是在这个方法上        实现的,调用的ReflectiveMethodInvocation.proceed方法,此方法执行完成后,        切面方法以及被监控bean实际需要执行的方法在此都会被执行,下方有具体实现源码        注意:本次分析的是jdk动态代理,cglib代理逻辑和jdk类似,不过源码不同*/				retVal = invocation.proceed();			}			//获取方法返回值			Class<?> returnType = method.getReturnType();			if (retVal != null && retVal == target &&					returnType != Object.class && returnType.isInstance(proxy) &&					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {				//如果需要返回代理对象,则直接返回代理对象				retVal = proxy;			}			return retVal;		}	}/*ReflectiveMethodInvocation.proceed方法,注意此方法会被多次调用,每次调用对象都是同一个对象,即JdkDynamicAopProxy.invoke方法 下面这行代码创建的对象,需要记住*///MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);public Object proceed() throws Throwable {		/*currentInterceptorIndex初始值为-1,interceptorsAndDynamicMethodMatchers长度为5,  即当前被监控的bean的所有增强器加上系统自带的增强器,我们分别配置了  Before、After、AfterReturning、AfterThrowing四个增强器,  系统自带了一个advisor增强器,这段逻辑的意思为,只有所有的增强器对应的监控方法  (invoke)过后,才会执行真实的方法,即invokeJoinpoint()*/		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {			return invokeJoinpoint();		}   /*从缓存中获取对应的方法拦截器,分别为:   ExposeInvocationInterceptor-系统自带拦截器   MethodBeforeAdviceInterceptor-前置通知拦截器   AspectJAfterAdvice-后置通知增强器   AfterReturningAdviceInterceptor--返回通知拦截器   AspectJAfterThrowingAdvice--异常通知拦截器*/		Object interceptorOrInterceptionAdvice =				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);  //上述5中拦截器均未实现或者继承InterceptorAndDynamicMethodMatcher,故省略内部逻辑		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {		}		else {      //调用拦截器对应的invoke方法,下面会按调用顺序将五种拦截器的源码附上			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);		}	}//ExposeInvocationInterceptor.invoke方法public Object invoke(MethodInvocation mi) throws Throwable {  //防止调用过程中方法调用器被修改,因此此处先存起来,执行拦截器执行结束后,将方法调用器重新赋值		MethodInvocation oldInvocation = invocation.get();		invocation.set(mi);		try {      /*调用MethodInvocation.proceed方法,此次调用后,invocation对象      内部属性currentInterceptorIndex会变成1,当proceed方法再次执行到88行代码时,      interceptorOrInterceptionAdvice对象就已经变成MethodBeforeAdviceInterceptor,      即所谓的前置通知拦截器*/			return mi.proceed();		}		finally {			invocation.set(oldInvocation);		}	}//MethodBeforeAdviceInterceptor.invokepublic Object invoke(MethodInvocation mi) throws Throwable {  /*此处执行@Before修饰的切面方法,这也解释了@Before修饰的方法块,永远在  业务方法执行钱会执行了*/		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); /*继续调用MethodInvocation.proceed方法,此次调用后,invocation对象      内部属性currentInterceptorIndex会变成2,当proceed方法再次执行到88行代码时,      interceptorOrInterceptionAdvice对象就已经变成AspectJAfterAdvice,      即所谓的后置通知拦截器*/		return mi.proceed();	}//AspectJAfterAdvice.invokepublic Object invoke(MethodInvocation mi) throws Throwable {		try {      /*继续调用MethodInvocation.proceed方法,此次调用后,invocation对象      内部属性currentInterceptorIndex会变成3,当proceed方法再次执行到88行代码时,      interceptorOrInterceptionAdvice对象就已经变成AfterReturningAdviceInterceptor,      即所谓的返回通知拦截器*/			return mi.proceed();		}		finally {      /*此处时执行@After注解修饰的切面,这也说明了,为什么@After修饰的方法块      永远在最后且一定会执行*/			invokeAdviceMethod(getJoinPointMatch(), null, null);		}	}//AfterReturningAdviceInterceptor.invokepublic Object invoke(MethodInvocation mi) throws Throwable {  /*继续调用MethodInvocation.proceed方法,此次调用后,invocation对象      内部属性currentInterceptorIndex会变成4,当proceed方法再次执行到88行代码时,      interceptorOrInterceptionAdvice对象就已经变成AspectJAfterThrowingAdvice,      即所谓的异常通知拦截器*/		Object retVal = mi.proceed();   /*如果上一步执行正常,则会执行@AfterReturning注解修饰的方法快,加入上一步执行出现异常,  则@AfterReturning不会执行*/		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());		return retVal;	}//AspectJAfterThrowingAdvice.invoke方法public Object invoke(MethodInvocation mi) throws Throwable {		try {        /*继续调用MethodInvocation.proceed方法,此次调用后,invocation对象      内部属性currentInterceptorIndex会变成5,当proceed方法再次执行到72行代码时,      if判断结果为true,则会真正开始执行被监控bean对应的业务方法*/			return mi.proceed();		}		catch (Throwable ex) {      //判断当前类型是否需要执行异常通知方法			if (shouldInvokeOnThrowing(ex)) {        //执行@AfterThrowing修饰的代码块,这样就可以在业务代码执行异常之后,去做一些特殊处理				invokeAdviceMethod(getJoinPointMatch(), null, ex);			}			throw ex;		}	}

以上就是Spring aop 代理的实际运行原理,主要使用的是责任链模式以及代理模式两种设计模式,从而高效达到一个动态实时代理的功能[灵光一闪]

标签: #aop代理机制