spring-reading./spring-aop/spring-aop-advisorChainFactory
linlei 0f740c2cd6 AdvisorChainFactory源码分析
AdvisorAdapterRegistry源码分析
2024-04-19 11:11:18 +08:00
..
src/main/java/com/xcs/spring AdvisorChainFactory源码分析 2024-04-19 11:11:18 +08:00
README.md AdvisorChainFactory源码分析 2024-04-19 11:11:18 +08:00
pom.xml AdvisorChainFactory源码分析 2024-04-19 11:11:18 +08:00

README.md

AdvisorChainFactory

一、基本信息

✒️ 作者 - Lex 📝 博客 - 掘金 📚 源码地址 - github

二、基本描述

AdvisorChainFactory接口是Spring AOP中负责创建顾问链的工厂接口通过getInterceptorsAndDynamicInterceptionAdvice()方法,它能够将一组顾问对象转换为拦截器数组,用于管理和执行切面逻辑,提供了灵活性和可扩展性来定制切面的执行方式。

三、主要功能

  1. 创建顾问链Advisor Chain

    • 通过getInterceptorsAndDynamicInterceptionAdvice()方法,将一组顾问对象转换为拦截器数组,形成顾问链,用于在目标方法执行前后执行特定的操作。
  2. 动态顾问链的创建

    • 可以根据运行时的情况动态地创建顾问链,例如根据目标对象的类型或方法签名动态地决定哪些通知要被执行。

四、接口源码

AdvisorChainFactory接口 用于创建Advisor链的工厂接口。其中的方法 getInterceptorsAndDynamicInterceptionAdvice() 接受AOP配置Advised对象、被代理的方法以及目标类并返回一个包含MethodInterceptors的列表用于配置Advisor链。这个接口的目的是根据给定的配置确定在代理方法执行时应该应用哪些拦截器以及是否需要动态匹配方法。

/**
 * Advisor链工厂的工厂接口。
 * Factory interface for advisor chains.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 */
public interface AdvisorChainFactory {

	/**
	 * 根据给定的Advisor链配置确定一组MethodInterceptor对象。
	 * Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
	 * for the given advisor chain configuration.
	 * @param config 表示AOP配置的Advised对象
	 * @param method 被代理的方法
	 * @param targetClass 目标类可能为null表示没有目标对象的代理在这种情况下方法的声明类是下一个最佳选择
	 * @return 一个MethodInterceptors的列表也可能包括InterceptorAndDynamicMethodMatchers
	 */
	List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);

}

五、主要实现

  1. DefaultAdvisorChainFactory

    • 负责根据给定的AOP配置、被代理的方法和目标类确定应该应用哪些拦截器并支持动态方法匹配和缓存机制以提供高效的顾问链创建功能

六、最佳实践

使用DefaultAdvisorChainFactory类来创建Advisor链。首先创建了一个AdvisedSupport对象,配置了前置通知和后置返回通知。然后,指定了目标类和目标方法。接着,实例化了DefaultAdvisorChainFactory类,并调用其getInterceptorsAndDynamicInterceptionAdvice()方法获取Advisor链。最后打印了Advisor链中的拦截器。

public class AdvisorChainFactoryDemo {

    public static void main(String[] args) throws NoSuchMethodException {
        // 创建AOP配置对象
        AdvisedSupport config = new AdvisedSupport();
        // 添加前置通知
        config.addAdvice(new MyMethodBeforeAdvice());
        // 添加后置返回通知
        config.addAdvice(new MyAfterReturningAdvice());
        // 设置目标类
        Class<MyService> targetClass = MyService.class;
        // 获取目标方法
        Method method = targetClass.getDeclaredMethod("doSomething");

        // 创建默认的Advisor链工厂实例
        DefaultAdvisorChainFactory chainFactory = new DefaultAdvisorChainFactory();
        // 获取Advisor链
        List<Object> chain = chainFactory.getInterceptorsAndDynamicInterceptionAdvice(config, method, targetClass);
        // 打印Advisor链中的拦截器
        chain.forEach(System.out::println);
    }
}

运行结果显示了Advisor链中的两个拦截器分别是MethodBeforeAdviceInterceptorAfterReturningAdviceInterceptor。这些拦截器是根据配置的前置通知和后置返回通知生成的,用于在目标方法执行前后进行相应的操作。

org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor@215be6bb
org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor@4439f31e

七、源码分析

DefaultAdvisorChainFactory类。它提供了一种简单但确定的方法,根据给定的Advised对象在方法级别确定通知链的构建顺序。通过遍历配置的Advisor数组并根据Advisor的类型和Pointcut来确定应该应用哪些拦截器最终返回一个拦截器列表。在此过程中它支持动态方法匹配和引入拦截器的处理并提供了一个缓存机制来提高性能。

/**
 * 给定一个 {@link Advised} 对象,为一个方法确定一个通知链的简单但确定的方法。总是重新构建每个通知链;
 * 子类可以提供缓存功能。
 *
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @author Adrian Colyer
 * @since 2.0.3
 */
@SuppressWarnings("serial")
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

	@Override
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
			Advised config, Method method, @Nullable Class<?> targetClass) {

		// 获取Advisor适配器注册表
		AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
		// 获取AOP配置中的所有Advisor
		Advisor[] advisors = config.getAdvisors();
		// 创建一个拦截器列表
		List<Object> interceptorList = new ArrayList<>(advisors.length);
		// 获取实际类
		Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
		Boolean hasIntroductions = null;

		// 遍历所有Advisor
		for (Advisor advisor : advisors) {
			if (advisor instanceof PointcutAdvisor) {
				// 添加条件性地。
				PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
				if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
					// 获取Advisor的Pointcut和MethodMatcher
					MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
					boolean match;
					if (mm instanceof IntroductionAwareMethodMatcher) {
						if (hasIntroductions == null) {
							// 检查是否存在匹配的IntroductionAdvisor
							hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
						}
						match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
					}
					else {
						match = mm.matches(method, actualClass);
					}
					// 如果匹配则将Interceptor添加到拦截器列表中
					if (match) {
						MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
						if (mm.isRuntime()) {
							// 如果是动态匹配则创建一个新的InterceptorAndDynamicMethodMatcher对象
							for (MethodInterceptor interceptor : interceptors) {
								interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
							}
						}
						else {
							// 否则直接添加Interceptor
							interceptorList.addAll(Arrays.asList(interceptors));
						}
					}
				}
			}
			else if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
					// 如果是IntroductionAdvisor则直接获取Interceptor并添加到拦截器列表中
					Interceptor[] interceptors = registry.getInterceptors(advisor);
					interceptorList.addAll(Arrays.asList(interceptors));
				}
			}
			else {
				// 对于其他类型的Advisor直接获取Interceptor并添加到拦截器列表中
				Interceptor[] interceptors = registry.getInterceptors(advisor);
				interceptorList.addAll(Arrays.asList(interceptors));
			}
		}

		// 返回拦截器列表
		return interceptorList;
	}

	/**
	 * 判断Advisor中是否存在匹配的引入拦截器。
	 */
	private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
		for (Advisor advisor : advisors) {
			if (advisor instanceof IntroductionAdvisor) {
				IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
				if (ia.getClassFilter().matches(actualClass)) {
					return true;
				}
			}
		}
		return false;
	}

}

八、常见问题

  1. 拦截器未被正确应用

    • 如果AdvisorChainFactory未正确构建Advisor链可能会导致拦截器未按预期应用于目标方法。
  2. 动态方法匹配错误

    • 如果动态方法匹配器DynamicMethodMatcher未正确配置或应用可能会导致拦截器未在预期条件下执行。
  3. 引入拦截器未生效

    • 如果引入拦截器IntroductionInterceptor未被正确添加到Advisor链中可能会导致引入功能无法正常工作。