10_aop详细执行流程及通知的执行

2 篇文章 0 订阅

之前介绍了aop的代理对象的生成,本次将从源码介绍方法执行时切面类的通知是怎么执行的。我们将使用后置通知来看方法的执行。其他通知同理。

代码开发

配置

spring.xml

	<!--配置DI注解解析器-->
	<context:annotation-config/>
	<!--配置IoC注解解析器-->
	<context:component-scan base-package="com.gl"/>
	<bean id="beforelog" class="com.gl.pojo.AdviceLog" />
	<!--配置后置通知-->
	<aop:config>
		<aop:aspect ref="beforelog">
			<aop:after method="after" pointcut="execution(* com.gl.pojo.UserServiceImpl.*(..))"/>
		</aop:aspect>
	</aop:config>
切面类
public class AdviceLog  {
	public void after() throws Throwable {
		System.out.println("方法执行了");
	}
}
接口
public interface UserService {
	CustomService user();
}
实现类
@Service
public class UserServiceImpl implements UserService {

	@Override
	public CustomService user() {
		System.out.println("执行UserService");
		return customService;
	}
}

代码执行

ApplicationContext applicationContext=new ClassPathXmlApplicationContext("spring.xml");
UserService userService = applicationContext.getBean("userServiceImpl",UserService.class);
userService.user();

代码开发完后,现在来启动项目从源码来看方法的执行。

源码

初始化

在获取bean是会创建UserServiceImpl 的代理对象 。同时会初始化一些和aop相关的类

org.springframework.aop.aspectj.AspectJAfterAdvice 通知
org.springframework.aop.aspectj.AspectJPointcutAdvisor 切面类

初始化时bean的后置处理器会生成代理对象那么此时会将相关的advisor存放在代理对象中,后续执行方法时会使用到。

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass( (ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
		//ProxyFactory 创建 Porxy工厂
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (proxyFactory.isProxyTargetClass()) {
			// Explicit handling of JDK proxy targets (for introduction advice scenarios)
			if (Proxy.isProxyClass(beanClass)) {
				// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
				for (Class<?> ifc : beanClass.getInterfaces()) {
					proxyFactory.addInterface(ifc);
				}
			}
		}
		else {
			// No proxyTargetClass flag enforced, let's apply our default checks...
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		// 在这一步会去判断advisors中是否存在IntroductionAdvisor,如果存在则会把对应的interface添加到proxyFactory中去
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// Use original ClassLoader if bean class not locally loaded in overriding class loader
		ClassLoader classLoader = getProxyClassLoader();
		if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
			classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
		}
		//返回对象
		return proxyFactory.getProxy(classLoader);
	}

封装ProxyFactory 工厂时proxyFactory.addAdvisors(advisors); 将使用到的切面类添加。

方法执行

由于我们实现了接口,那么会使用到jdk动态代理

class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable 

因为JdkDynamicAopProxy 实现了InvocationHandler 接口,那么JdkDynamicAopProxy 会实现invoke 方法。那么当我们的方法执行的时候会执行invoke 方法。那么我们来看下invoke 方法的实现。

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 {
			// 如果接口中没有定义equals()方法,那么则直接调用,不走代理
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// The target does not implement the equals(Object) method itself.
				return equals(args[0]);
			}
			else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
				// The target does not implement the hashCode() method itself.
				return hashCode();
			}
			else if (method.getDeclaringClass() == DecoratingProxy.class) {
				// There is only getDecoratedClass() declared -> dispatch to proxy config.
				// 得到代理对象的类型,而不是所实现的接口
				return AopProxyUtils.ultimateTargetClass(this.advised);
			}
			else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
					method.getDeclaringClass().isAssignableFrom(Advised.class)) {
				// Service invocations on ProxyConfig with the proxy config...
				// 也是直接调用Advised接口中的方法,不走代理逻辑
				// 其实就是利用代理对象获取ProxyFactory中的信息
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			// 如果ProxyFactory的exposeProxy为true,则将代理对象设置到currentProxy这个ThreadLocal中去
			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}
			// 被代理对象和代理类
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			// 代理对象在执行某个方法时,根据方法筛选出匹配的Advisor,并适配成Interceptor
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			if (chain.isEmpty()) {
				// 如果没有Advice,则直接调用对应方法
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				
				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;
			}
			else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
				throw new AopInvocationException(
						"Null return value from advice does not match primitive return type for: " + method);
			}
			return retVal;
		}
		finally {
			if (target != null && !targetSource.isStatic()) {
				// Must have come from TargetSource.
				targetSource.releaseTarget(target);
			}
			if (setProxyContext) {
				// Restore old proxy.
				AopContext.setCurrentProxy(oldProxy);
			}
		}
	}

以上最重要的是查询到通知

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

在这里插入图片描述
会发现他已经查询到了初始化的后置通知类

org.springframework.aop.aspectj.AspectJAfterAdvice: advice method [public void com.gl.pojo.AdviceLog.after() throws java.lang.Throwable]; aspect name 'beforelog'

下面开始执行方法及后置通知

MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();

进入proceed方法

public Object proceed() throws Throwable {

		// We start with an index of -1 and increment early.
		// currentInterceptorIndex初始值为-1,每调用一个interceptor就会加1
		// 当调用完了最后一个interceptor后就会执行被代理方法
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		// currentInterceptorIndex初始值为-1
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

		// 当前interceptor是InterceptorAndDynamicMethodMatcher,则先进行匹配,匹配成功后再调用该interceptor
		// 如果没有匹配则递归调用proceed()方法,调用下一个interceptor
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
			// 动态匹配,根据方法参数匹配
			if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				// 不匹配则执行下一个MethodInterceptor
				return proceed();
			}
		}
		else {

			// It's an interceptor, so we just invoke it: The pointcut will have
			// been evaluated statically before this object was constructed.
			// 直接调用MethodInterceptor,传入this,在内部会再次调用proceed()方法进行递归
			// 比如MethodBeforeAdviceInterceptor
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

会执行 MethodInterceptor 接口的 invoke

((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);

MethodInterceptor 的实现类包含了后置 、异常、环绕、前置
所以说 MethodInterceptor这个接口很重要 真正的执行方法和通知 是 MethodInterceptor 的实现类实现的。

AspectJAfterAdvice
AspectJAfterThrowingAdvice
AspectJAroundAdvice
MethodBeforeAdviceInterceptor

我们进入到后置通知的实现类

public Object invoke(MethodInvocation mi) throws Throwable {
		try {
			//执行原始方法
			return mi.proceed();
		}
		finally {
			//执行后置方法
			invokeAdviceMethod(getJoinPointMatch(), null, null);
		}
	}

执行原始方法
在这里插入图片描述
在这里插入图片描述
之后执行invokeAdviceMethod(getJoinPointMatch(), null, null);

protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
		Object[] actualArgs = args;
		if (this.aspectJAdviceMethod.getParameterCount() == 0) {
			actualArgs = null;
		}

		// 反射调用aspectJAdviceMethod方法
		try {
			ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
			// 拿到Advice中所记录的LazySingletonAspectInstanceFactoryDecorator对象从而获得切面Bean实例,再执行对应方法
			// 一个代理对象可能会对应多个Advisor,也就是Advice,而这些Advice在生成时都是用的同一个LazySingletonAspectInstanceFactoryDecorator
			// 不过一个类如果和某个perthis、pertarget的切面匹配的话,在生成的代理对象中还会有一个额外的Advisor,这个Advisor会负责
			return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
		}
		catch (IllegalArgumentException ex) {
			throw new AopInvocationException("Mismatch on arguments to advice method [" +
					this.aspectJAdviceMethod + "]; pointcut expression [" +
					this.pointcut.getPointcutExpression() + "]", ex);
		}
		catch (InvocationTargetException ex) {
			throw ex.getTargetException();
		}
	}

重要方法
aspectJAdviceMethod是Method类型

this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);

在这里插入图片描述
从工厂根据bean名称获取bean对象执行after方法。
这里会用到jdk中Method类的invoke方法
熟悉反射的会比较熟悉 ,在学习反射时执行方法会用到该方法。在这里执行后置方法同理。

Object invoke(Object obj, Object... args)

在这里插入图片描述
控制台后置方法执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值