## 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类型的适配器,或者适配器的实现存在缺陷。