Spring AOP 链式调用过程源码解析

引言

概述: AOP系列文章:
【1】Spring Aop初始化源码分析
【2】Spring AOP创建代理对象源码解析
【3】Spring AOP 链式调用过程源码解析
【4】Spring 事务执行过程源码解析

1 工程概述

在这里插入图片描述

1.1 pom

 <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.2.8.RELEASE</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
        </dependency>
        <!-- 日志相关依赖 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.10</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

1.2 配置文件

@Configuration
@EnableAspectJAutoProxy
@Import(ServiceAopConfig.class)
public class AopConfig {


}

@Configuration
@Aspect
public class ServiceAopConfig {

    /**
     * 声明切点
     */
    @Pointcut("execution(* com.rosh.service.*.*(..))")
    public void pointCut() {

    }

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("ServiceAopConfig invoke around start");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("ServiceAopConfig invoke around end");
        return proceed;
    }

    @Before("pointCut()")
    public void before(){
        System.out.println("ServiceAopConfig invoke before");
    }

    @After("pointCut()")
    public void after() {
        System.out.println("ServiceAopConfig invoke after");
    }
}


1.3 Service

public interface StudentService {

     void addStudent();

}


@Service
public class StudentServiceImpl implements StudentService {

    @Override
    public void addStudent() {
        System.out.println("StudentServiceImpl invoke addStudent()");
    }
}


1.4 RoshTest

public class RoshTest {

    @Test
    public void mainTest(){

        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.rosh");
        StudentService studentService = (StudentService) applicationContext.getBean("studentServiceImpl");
        studentService.addStudent();


    }

}

1. 5 结果

在这里插入图片描述

2 前置步骤概述

(1) BeanFactoryAspectJAdvisorsBuilder会收集项目中所有advisor(pointCut+advice)(2) AbstractAutoProxyCreator在进行后置增强时,会获取当前bean的有效advisor列表。
(3) 如果advisor列表不为空那么创建代理对象,首先创建ProxyFactory工厂配置增强类型(默认使用JDK,如果当前增强bean不是接口实现类,那么使用cglib),一个代理对象对应一个代理工厂,并把有效的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);
		}

		/**
		 *  【1】创建代理工厂,赋值。
		 */
		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		/**
		 * 【2】 proxyTargetClass为true时代表使用cglib,为false使用jdk,默认值是false。
		 *  判断当前被代理对象是使用jdk增强还是使用cglib增强
		 *
		 */
		if (!proxyFactory.isProxyTargetClass()) {
			//根据最开始@EnableAspectJAutoProxy注解中的proxyTargetClass参数判断是否应该使用cglib代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				//如果是接口增强那么使用jdk,否则使用cglib
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		//构建advisor
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//把advisor加入到代理工厂中
		proxyFactory.addAdvisors(advisors);
		//把targetSource对象加入代理工厂(实际对象、被代理对象)
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

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

		/**
		 * 【3】 获取代理对象
		 */
		return proxyFactory.getProxy(getProxyClassLoader());
	}

3 调取源码解析

描述: JdkDynamicAopProxy invoke方法详解:

@Override
	@Nullable
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		/**
		 * 【1】获取代理工厂
		 */
		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			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...
				return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
			}

			Object retVal;

			if (this.advised.exposeProxy) {
				// Make invocation available if necessary.
				oldProxy = AopContext.setCurrentProxy(proxy);
				setProxyContext = true;
			}

			// Get as late as possible to minimize the time we "own" the target,
			// in case it comes from a pool.
			/**
			 * 【2】 获取真实对象
			 */
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// Get the interception chain for this method.
			/**
			 * 【3】 获取方法链
			 *
			 *  (1) 根据代理工厂获取有效的advisors
			 *  (2) 遍历advisors,匹配类、匹配方法为true的advisor,获取advice,封装成MethodInterceptor对象。
			 *  (3) 将构建出来的MethodInterceptor对象,添加到拦截链中。
			 *
			 */
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			// Check whether we have any advice. If we don't, we can fallback on direct
			// reflective invocation of the target, and avoid creating a MethodInvocation.

			/**
			 * 【4】 如果没有调用链,直接反射调用方法
			 */
			if (chain.isEmpty()) {
				// We can skip creating a MethodInvocation: just invoke the target directly
				// Note that the final invoker must be an InvokerInterceptor so we know it does
				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
				// We need to create a method invocation...
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				// Proceed to the joinpoint through the interceptor chain.

				/**
				 * 【5】 链式调取
				 */
				retVal = invocation.proceed();
			}

			// Massage return value if necessary.
			Class<?> returnType = method.getReturnType();
			if (retVal != null && retVal == target &&
					returnType != Object.class && returnType.isInstance(proxy) &&
					!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
				// Special case: it returned "this" and the return type of the method
				// is type-compatible. Note that we can't help if the target sets
				// a reference to itself in another returned object.
				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);
			}
		}
	}

4 获取调用链源码解析

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {

			/**
			 * 获取调用链
			 */
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}
@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// This is somewhat tricky... We have to process introductions first,
		// but we need to preserve order in the ultimate list.
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

		/**
		 * 【1】 从代理工厂中获取真实对象(被代理对象)的advisor
		 */
		Advisor[] advisors = config.getAdvisors();
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				// Add it conditionally.
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

				/**
				 * 【2】 判断advisor是否匹配类和方法
				 */
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						match = mm.matches(method, actualClass);
					}

					/**
					 * 【3】 如果pointcut 匹配类 并且匹配方法
					 */
					if (match) {
						//获取advisor中的advice,并且包装成MethodInterceptor类型的对象
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							// Creating a new object instance in the getInterceptors() method
							// isn't a problem as we normally cache created chains.
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		return interceptorList;
	}

5 debug

5.1 获取调用链

在这里插入图片描述
描述: 从代理工厂中获取当前类有效的advisor,遍历advisor。
在这里插入图片描述

描述: 如果pointCut 匹配类,匹配方法那么把advice封装成MethodInterceptor对象并且存入返回链中。

在这里插入图片描述

描述: 获取调用链
在这里插入图片描述

5.2 调取分析

在这里插入图片描述

描述: 终止条件,索引等于最后一个advice。
在这里插入图片描述
描述: 链式调用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

响彻天堂丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值