From 0f740c2cd668f73a1c7b1d1eb45208cf2cc638f6 Mon Sep 17 00:00:00 2001 From: linlei Date: Fri, 19 Apr 2024 11:11:18 +0800 Subject: [PATCH] =?UTF-8?q?AdvisorChainFactory=E6=BA=90=E7=A0=81=E5=88=86?= =?UTF-8?q?=E6=9E=90=20AdvisorAdapterRegistry=E6=BA=90=E7=A0=81=E5=88=86?= =?UTF-8?q?=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + spring-aop/pom.xml | 2 + .../README.md | 240 ++++++++++++++++++ .../spring-aop-advisorAdapterRegistry/pom.xml | 14 + .../spring/AdvisorAdapterRegistryDemo.java | 22 ++ .../com/xcs/spring/MyMethodBeforeAdvice.java | 12 + .../spring-aop-advisorChainFactory/README.md | 216 ++++++++++++++++ .../spring-aop-advisorChainFactory/pom.xml | 14 + .../xcs/spring/AdvisorChainFactoryDemo.java | 30 +++ .../xcs/spring/MyAfterReturningAdvice.java | 12 + .../com/xcs/spring/MyMethodBeforeAdvice.java | 12 + .../main/java/com/xcs/spring/MyService.java | 8 + 12 files changed, 584 insertions(+) create mode 100644 spring-aop/spring-aop-advisorAdapterRegistry/README.md create mode 100644 spring-aop/spring-aop-advisorAdapterRegistry/pom.xml create mode 100644 spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/AdvisorAdapterRegistryDemo.java create mode 100644 spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java create mode 100644 spring-aop/spring-aop-advisorChainFactory/README.md create mode 100644 spring-aop/spring-aop-advisorChainFactory/pom.xml create mode 100644 spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/AdvisorChainFactoryDemo.java create mode 100644 spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyAfterReturningAdvice.java create mode 100644 spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java create mode 100644 spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyService.java diff --git a/README.md b/README.md index fbab7b4..a9b2393 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,8 @@ - [BeanFactoryAspectJAdvisorsBuilder](spring-aop/spring-aop-beanFactoryAspectJAdvisorsBuilder/README.md):构建@AspectJ注解切面,生成Spring AOP Advisors。 - [BeanFactoryAdvisorRetrievalHelper](spring-aop/spring-aop-beanFactoryAdvisorRetrievalHelper/README.md):帮助检索并管理 Spring AOP 中的 Advisor Beans。 - [AnnotationAwareAspectJAutoProxyCreator](spring-aop/spring-aop-annotationAwareAspectJAutoProxyCreator/README.md):创建AOP代理以应用AspectJ风格的切面。 + - [AdvisorChainFactory](spring-aop/spring-aop-advisorChainFactory/README.md):创建Advisor链的工厂接口。 + - [AdvisorAdapterRegistry](spring-aop/spring-aop-advisorAdapterRegistry/README.md):适配各种Advice到AOP拦截器,注册和管理Advisor适配器。 + Spring AOT diff --git a/spring-aop/pom.xml b/spring-aop/pom.xml index 86c0fa6..01dc2ea 100644 --- a/spring-aop/pom.xml +++ b/spring-aop/pom.xml @@ -33,6 +33,8 @@ spring-aop-beanFactoryAspectJAdvisorsBuilder spring-aop-beanFactoryAdvisorRetrievalHelper spring-aop-proxyFactory + spring-aop-advisorChainFactory + spring-aop-advisorAdapterRegistry 4.0.0 diff --git a/spring-aop/spring-aop-advisorAdapterRegistry/README.md b/spring-aop/spring-aop-advisorAdapterRegistry/README.md new file mode 100644 index 0000000..fed612a --- /dev/null +++ b/spring-aop/spring-aop-advisorAdapterRegistry/README.md @@ -0,0 +1,240 @@ +## AdvisorAdapterRegistry + +- [AdvisorAdapterRegistry](#AdvisorAdapterRegistry) + - [一、基本信息](#一基本信息) + - [二、基本描述](#二基本描述) + - [三、主要功能](#三主要功能) + - [四、接口源码](#四接口源码) + - [五、主要实现](#五主要实现) + - [六、最佳实践](#六最佳实践) + - [七、源码分析](#七源码分析) + - [八、常见问题](#八常见问题) + +### 一、基本信息 + +✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https://github.com/xuchengsheng/spring-reading) + +### 二、基本描述 + +`AdvisorAdapterRegistry`接口是Spring AOP中的关键接口之一,用于注册和管理AdvisorAdapters,它负责将Advisor与AOP框架所支持的特定拦截器关联起来,实现对目标对象方法的拦截和增强,从而实现面向切面编程的功能。 + +### 三、主要功能 + +1. **注册AdvisorAdapters** + + + 允许我们注册自定义的AdvisorAdapters,以适配新的拦截器类型或扩展现有的拦截器逻辑。 + +3. **支持内置拦截器** + + + 默认实现预先注册了一些标准的AdvisorAdapters,用于支持Spring AOP框架内置的拦截器类型(如BeforeAdvice、AfterReturningAdvice等)。 + +### 四、接口源码 + +作为Advisor适配器的注册表。它提供了方法来包装给定的advice为Advisor,并获取Advisor中的拦截器数组。通过注册AdvisorAdapter,实现了Advisor与AOP框架所支持的不同拦截器类型之间的适配。 + +```java +/** + * Advisor适配器注册表的接口。 + * + *

这是一个SPI接口,不应该由任何Spring用户实现。 + * + * @author Rod Johnson + * @author Rob Harrop + */ +public interface AdvisorAdapterRegistry { + + /** + * 返回一个包装了给定advice的{@link Advisor}。 + *

默认情况下应该至少支持 + * {@link org.aopalliance.intercept.MethodInterceptor}, + * {@link org.springframework.aop.MethodBeforeAdvice}, + * {@link org.springframework.aop.AfterReturningAdvice}, + * {@link org.springframework.aop.ThrowsAdvice}。 + * @param advice 应该是一个advice的对象 + * @return 包装了给定advice的Advisor(永远不会为{@code null}; + * 如果advice参数本身就是一个Advisor,则直接返回) + * @throws UnknownAdviceTypeException 如果没有注册的advisor adapter + * 能够包装给定的advice + */ + Advisor wrap(Object advice) throws UnknownAdviceTypeException; + + /** + * 返回一组AOP Alliance MethodInterceptors,以允许在基于拦截的框架中使用给定的Advisor。 + *

如果Advisor是一个{@link org.springframework.aop.PointcutAdvisor}, + * 则不必担心与其关联的切入点表达式只需返回一个拦截器。 + * @param advisor 要查找拦截器的Advisor + * @return 一组MethodInterceptor,用于暴露此Advisor的行为 + * @throws UnknownAdviceTypeException 如果Advisor类型 + * 不被任何注册的AdvisorAdapter理解 + */ + MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException; + + /** + * 注册给定的{@link AdvisorAdapter}。 + * 注意,不需要为AOP Alliance Interceptors或Spring Advices注册适配器 + * 这些必须由{@code AdvisorAdapterRegistry}的实现自动识别。 + * @param adapter 理解特定Advisor或Advice类型的AdvisorAdapter + */ + void registerAdvisorAdapter(AdvisorAdapter adapter); + +} +``` + +### 五、主要实现 + +1. **DefaultAdvisorAdapterRegistry** + + + 默认Advisor适配器注册表实现,预先注册了标准的Advisor适配器,支持将各种类型的Advice适配到AOP Alliance MethodInterceptor,并允许我们注册自定义的Advisor适配器,从而实现了Advisor与拦截器之间的灵活适配和管理。 + +### 六、最佳实践 + +使用`DefaultAdvisorAdapterRegistry`来包装自定义的`MyMethodBeforeAdvice`,并获取其对应的拦截器数组。通过`wrap()`方法将`MyMethodBeforeAdvice`转换为`Advisor`,然后使用`getInterceptors()`方法获取该`Advisor`中的拦截器数组,最后输出拦截器的信息。 + +```java +public class AdvisorAdapterRegistryDemo { + + public static void main(String[] args) { + // 创建默认的Advisor适配器注册表实例 + DefaultAdvisorAdapterRegistry registry = new DefaultAdvisorAdapterRegistry(); + // 包装给定的MyMethodBeforeAdvice为Advisor + Advisor advisor = registry.wrap(new MyMethodBeforeAdvice()); + + // 获取Advisor中的拦截器数组 + MethodInterceptor[] interceptors = registry.getInterceptors(advisor); + // 输出拦截器信息 + for (MethodInterceptor interceptor : interceptors) { + System.out.println("interceptor = " + interceptor); + } + } +} +``` + +### 七、源码分析 + +实现了`AdvisorAdapterRegistry`接口的默认实现`DefaultAdvisorAdapterRegistry`,支持将不同类型的Advice对象适配为Advisor,并提供获取Advisor中拦截器数组的功能。它预先注册了一些常见的Advisor适配器,并允许用户注册自定义的适配器。其核心逻辑包括将Advice对象包装为Advisor、根据Advisor获取拦截器数组以及注册Advisor适配器。 + +```java +/** + * AdvisorAdapterRegistry接口的默认实现。 + * 支持{@link org.aopalliance.intercept.MethodInterceptor}、 + * {@link org.springframework.aop.MethodBeforeAdvice}、 + * {@link org.springframework.aop.AfterReturningAdvice}、 + * {@link org.springframework.aop.ThrowsAdvice}。 + * + * @author Rod Johnson + * @author Rob Harrop + * @author Juergen Hoeller + */ +@SuppressWarnings("serial") +public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable { + + // 用于存储注册的AdvisorAdapter的列表 + private final List adapters = new ArrayList<>(3); + + /** + * 创建一个新的DefaultAdvisorAdapterRegistry实例,并注册已知的适配器。 + * 这里的“已知的适配器”包括MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter。 + */ + public DefaultAdvisorAdapterRegistry() { + // 注册MethodBeforeAdviceAdapter适配器 + registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); + // 注册AfterReturningAdviceAdapter适配器 + registerAdvisorAdapter(new AfterReturningAdviceAdapter()); + // 注册ThrowsAdviceAdapter适配器 + registerAdvisorAdapter(new ThrowsAdviceAdapter()); + } + + /** + * 将给定的adviceObject包装为Advisor。 + * 如果adviceObject已经是Advisor,则直接返回; + * 如果不是Advice类型,则抛出UnknownAdviceTypeException; + * 如果advice是MethodInterceptor类型,则创建一个DefaultPointcutAdvisor并返回; + * 否则,遍历已注册的AdvisorAdapter,找到支持advice的适配器,创建一个DefaultPointcutAdvisor并返回。 + * + * @param adviceObject 要包装为Advisor的Advice对象 + * @return 包装后的Advisor对象 + * @throws UnknownAdviceTypeException 如果adviceObject无法被识别为Advisor或Advice + */ + @Override + public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException { + if (adviceObject instanceof Advisor) { + return (Advisor) adviceObject; + } + if (!(adviceObject instanceof Advice)) { + throw new UnknownAdviceTypeException(adviceObject); + } + Advice advice = (Advice) adviceObject; + if (advice instanceof MethodInterceptor) { + // 对于MethodInterceptor类型的Advice,不需要适配器,直接创建Advisor并返回 + return new DefaultPointcutAdvisor(advice); + } + // 遍历已注册的AdvisorAdapter,查找支持当前Advice的适配器 + for (AdvisorAdapter adapter : this.adapters) { + // 检查是否支持当前Advice + if (adapter.supportsAdvice(advice)) { + // 创建Advisor并返回 + return new DefaultPointcutAdvisor(advice); + } + } + // 如果无法找到合适的适配器,抛出异常 + throw new UnknownAdviceTypeException(advice); + } + + /** + * 获取Advisor中的拦截器数组。 + * 如果Advisor中的Advice是MethodInterceptor类型,则直接返回; + * 否则,遍历已注册的AdvisorAdapter,找到支持Advisor中的Advice的适配器,并获取对应的拦截器,返回拦截器数组。 + * + * @param advisor 要获取拦截器数组的Advisor对象 + * @return 包含Advisor中拦截器的数组 + * @throws UnknownAdviceTypeException 如果Advisor中的Advice无法被识别 + */ + @Override + public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { + List interceptors = new ArrayList<>(3); + Advice advice = advisor.getAdvice(); + // 如果Advisor中的Advice是MethodInterceptor类型,直接将其添加到拦截器数组中 + if (advice instanceof MethodInterceptor) { + interceptors.add((MethodInterceptor) advice); + } + // 遍历已注册的AdvisorAdapter,查找支持Advisor中的Advice的适配器 + for (AdvisorAdapter adapter : this.adapters) { + // 如果适配器支持当前Advice,获取其拦截器并添加到数组中 + if (adapter.supportsAdvice(advice)) { + interceptors.add(adapter.getInterceptor(advisor)); + } + } + // 如果拦截器数组为空,表示未找到适配器,抛出异常 + if (interceptors.isEmpty()) { + throw new UnknownAdviceTypeException(advice); + } + // 将拦截器数组转换为数组并返回 + return interceptors.toArray(new MethodInterceptor[0]); + } + + /** + * 注册给定的AdvisorAdapter。 + * + * @param adapter 要注册的AdvisorAdapter对象 + */ + @Override + public void registerAdvisorAdapter(AdvisorAdapter adapter) { + this.adapters.add(adapter); + } + +} +``` + +### 八、常见问题 + +1. **适配器未注册** + + - 如果尝试使用某种类型的Advice对象,而对应的适配器未被注册到`AdvisorAdapterRegistry`实例中,可能会导致无法将Advice对象包装为Advisor,进而导致运行时异常。 + +2. **适配器不支持特定类型的Advice** + + - 每个Advisor适配器可能只支持特定类型的Advice,如果尝试使用一个不受支持的Advice对象,可能会导致运行时异常或者Advice对象无法被正确地适配为Advisor。 + +3. **Advice对象无法被正确适配** + + - 某些特定类型的Advice对象可能无法被任何已注册的适配器正确地适配为Advisor。这可能是因为没有适合该Advice类型的适配器,或者适配器的实现存在缺陷。 \ No newline at end of file diff --git a/spring-aop/spring-aop-advisorAdapterRegistry/pom.xml b/spring-aop/spring-aop-advisorAdapterRegistry/pom.xml new file mode 100644 index 0000000..65f4dcc --- /dev/null +++ b/spring-aop/spring-aop-advisorAdapterRegistry/pom.xml @@ -0,0 +1,14 @@ + + + + com.xcs.spring + spring-aop + 0.0.1-SNAPSHOT + + + 4.0.0 + spring-aop-advisorAdapterRegistry + + \ No newline at end of file diff --git a/spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/AdvisorAdapterRegistryDemo.java b/spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/AdvisorAdapterRegistryDemo.java new file mode 100644 index 0000000..cc50f24 --- /dev/null +++ b/spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/AdvisorAdapterRegistryDemo.java @@ -0,0 +1,22 @@ +package com.xcs.spring; + +import org.aopalliance.intercept.MethodInterceptor; +import org.springframework.aop.Advisor; +import org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry; + +public class AdvisorAdapterRegistryDemo { + + public static void main(String[] args) { + // 创建默认的Advisor适配器注册表实例 + DefaultAdvisorAdapterRegistry registry = new DefaultAdvisorAdapterRegistry(); + // 包装给定的MyMethodBeforeAdvice为Advisor + Advisor advisor = registry.wrap(new MyMethodBeforeAdvice()); + + // 获取Advisor中的拦截器数组 + MethodInterceptor[] interceptors = registry.getInterceptors(advisor); + // 输出拦截器信息 + for (MethodInterceptor interceptor : interceptors) { + System.out.println("interceptor = " + interceptor); + } + } +} diff --git a/spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java b/spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java new file mode 100644 index 0000000..16e23b3 --- /dev/null +++ b/spring-aop/spring-aop-advisorAdapterRegistry/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java @@ -0,0 +1,12 @@ +package com.xcs.spring; + +import org.springframework.aop.MethodBeforeAdvice; + +import java.lang.reflect.Method; + +public class MyMethodBeforeAdvice implements MethodBeforeAdvice { + @Override + public void before(Method method, Object[] args, Object target) throws Throwable { + System.out.println("Before method: " + method.getName()); + } +} diff --git a/spring-aop/spring-aop-advisorChainFactory/README.md b/spring-aop/spring-aop-advisorChainFactory/README.md new file mode 100644 index 0000000..b7b1a23 --- /dev/null +++ b/spring-aop/spring-aop-advisorChainFactory/README.md @@ -0,0 +1,216 @@ +## AdvisorChainFactory + +- [AdvisorChainFactory](#AdvisorChainFactory) + - [一、基本信息](#一基本信息) + - [二、基本描述](#二基本描述) + - [三、主要功能](#三主要功能) + - [四、接口源码](#四接口源码) + - [五、主要实现](#五主要实现) + - [六、最佳实践](#六最佳实践) + - [七、源码分析](#七源码分析) + - [八、常见问题](#八常见问题) + +### 一、基本信息 + +✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址** - [github](https://github.com/xuchengsheng/spring-reading) + +### 二、基本描述 + +`AdvisorChainFactory`接口是Spring AOP中负责创建顾问链的工厂接口,通过`getInterceptorsAndDynamicInterceptionAdvice()`方法,它能够将一组顾问对象转换为拦截器数组,用于管理和执行切面逻辑,提供了灵活性和可扩展性来定制切面的执行方式。 + +### 三、主要功能 + +1. **创建顾问链(Advisor Chain)** + + + 通过`getInterceptorsAndDynamicInterceptionAdvice()`方法,将一组顾问对象转换为拦截器数组,形成顾问链,用于在目标方法执行前后执行特定的操作。 + +2. **动态顾问链的创建** + + + 可以根据运行时的情况动态地创建顾问链,例如根据目标对象的类型或方法签名动态地决定哪些通知要被执行。 + +### 四、接口源码 + +`AdvisorChainFactory`接口 ,用于创建Advisor链的工厂接口。其中的方法 `getInterceptorsAndDynamicInterceptionAdvice()` 接受AOP配置(`Advised`对象)、被代理的方法以及目标类,并返回一个包含MethodInterceptors的列表,用于配置Advisor链。这个接口的目的是根据给定的配置,确定在代理方法执行时应该应用哪些拦截器,以及是否需要动态匹配方法。 + +```java +/** + * 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 getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class targetClass); + +} +``` + +### 五、主要实现 + +1. **DefaultAdvisorChainFactory** + + + 负责根据给定的AOP配置、被代理的方法和目标类,确定应该应用哪些拦截器,并支持动态方法匹配和缓存机制,以提供高效的顾问链创建功能 + +### 六、最佳实践 + +使用`DefaultAdvisorChainFactory`类来创建Advisor链。首先,创建了一个`AdvisedSupport`对象,配置了前置通知和后置返回通知。然后,指定了目标类和目标方法。接着,实例化了`DefaultAdvisorChainFactory`类,并调用其`getInterceptorsAndDynamicInterceptionAdvice()`方法获取Advisor链。最后,打印了Advisor链中的拦截器。 + +```java +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 targetClass = MyService.class; + // 获取目标方法 + Method method = targetClass.getDeclaredMethod("doSomething"); + + // 创建默认的Advisor链工厂实例 + DefaultAdvisorChainFactory chainFactory = new DefaultAdvisorChainFactory(); + // 获取Advisor链 + List chain = chainFactory.getInterceptorsAndDynamicInterceptionAdvice(config, method, targetClass); + // 打印Advisor链中的拦截器 + chain.forEach(System.out::println); + } +} +``` + +运行结果,显示了Advisor链中的两个拦截器,分别是`MethodBeforeAdviceInterceptor`和`AfterReturningAdviceInterceptor`。这些拦截器是根据配置的前置通知和后置返回通知生成的,用于在目标方法执行前后进行相应的操作。 + +```java +org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor@215be6bb +org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor@4439f31e +``` + +### 七、源码分析 + +`DefaultAdvisorChainFactory`类。它提供了一种简单但确定的方法,根据给定的`Advised`对象,在方法级别确定通知链的构建顺序。通过遍历配置的Advisor数组,并根据Advisor的类型和Pointcut来确定应该应用哪些拦截器,最终返回一个拦截器列表。在此过程中,它支持动态方法匹配和引入拦截器的处理,并提供了一个缓存机制来提高性能。 + +```java +/** + * 给定一个 {@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 getInterceptorsAndDynamicInterceptionAdvice( + Advised config, Method method, @Nullable Class targetClass) { + + // 获取Advisor适配器注册表 + AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); + // 获取AOP配置中的所有Advisor + Advisor[] advisors = config.getAdvisors(); + // 创建一个拦截器列表 + List 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链中,可能会导致引入功能无法正常工作。 \ No newline at end of file diff --git a/spring-aop/spring-aop-advisorChainFactory/pom.xml b/spring-aop/spring-aop-advisorChainFactory/pom.xml new file mode 100644 index 0000000..0e65829 --- /dev/null +++ b/spring-aop/spring-aop-advisorChainFactory/pom.xml @@ -0,0 +1,14 @@ + + + + com.xcs.spring + spring-aop + 0.0.1-SNAPSHOT + + + 4.0.0 + spring-aop-advisorChainFactory + + \ No newline at end of file diff --git a/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/AdvisorChainFactoryDemo.java b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/AdvisorChainFactoryDemo.java new file mode 100644 index 0000000..11a0c40 --- /dev/null +++ b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/AdvisorChainFactoryDemo.java @@ -0,0 +1,30 @@ +package com.xcs.spring; + +import org.springframework.aop.framework.AdvisedSupport; +import org.springframework.aop.framework.DefaultAdvisorChainFactory; + +import java.lang.reflect.Method; +import java.util.List; + +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 targetClass = MyService.class; + // 获取目标方法 + Method method = targetClass.getDeclaredMethod("doSomething"); + + // 创建默认的Advisor链工厂实例 + DefaultAdvisorChainFactory chainFactory = new DefaultAdvisorChainFactory(); + // 获取Advisor链 + List chain = chainFactory.getInterceptorsAndDynamicInterceptionAdvice(config, method, targetClass); + // 打印Advisor链中的拦截器 + chain.forEach(System.out::println); + } +} diff --git a/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyAfterReturningAdvice.java b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyAfterReturningAdvice.java new file mode 100644 index 0000000..c4c32a8 --- /dev/null +++ b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyAfterReturningAdvice.java @@ -0,0 +1,12 @@ +package com.xcs.spring; + +import org.springframework.aop.AfterReturningAdvice; + +import java.lang.reflect.Method; + +public class MyAfterReturningAdvice implements AfterReturningAdvice { + @Override + public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { + System.out.println("After method: " + method.getName()); + } +} diff --git a/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java new file mode 100644 index 0000000..16e23b3 --- /dev/null +++ b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyMethodBeforeAdvice.java @@ -0,0 +1,12 @@ +package com.xcs.spring; + +import org.springframework.aop.MethodBeforeAdvice; + +import java.lang.reflect.Method; + +public class MyMethodBeforeAdvice implements MethodBeforeAdvice { + @Override + public void before(Method method, Object[] args, Object target) throws Throwable { + System.out.println("Before method: " + method.getName()); + } +} diff --git a/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyService.java b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyService.java new file mode 100644 index 0000000..1bfa4fe --- /dev/null +++ b/spring-aop/spring-aop-advisorChainFactory/src/main/java/com/xcs/spring/MyService.java @@ -0,0 +1,8 @@ +package com.xcs.spring; + +public class MyService { + + public void doSomething(){ + System.out.println("doSomething"); + } +}