前言
上篇文章:【小家Spring】Spring AOP核心类Pointcut解析,对PointcutExpression切点表达式解析原理分析(以AspectJExpressionPointcut为例)
讲到了很多的Pointcut,以及各自的使用场景。
而Advisor是Pointcut以及Advice的一个结合,有着非常深的联系,因此本文主要扫盲一下Advisor
Advisor介绍
Advisor是Spring AOP的顶层抽象,用来管理Advice和Pointcut(PointcutAdvisor和切点有关,但IntroductionAdvisor和切点无关)
注意:Advice是aopalliance对通知(增强器)的顶层抽象,请注意区分~~
Pointcut是Spring AOP对切点的抽象。切点的实现方式有多种,其中一种就是AspectJ
public interface Advisor { //@since 5.0 Spring5以后才有的 空通知 一般当作默认值 Advice EMPTY_ADVICE = new Advice() {}; // 该Advisor 持有的通知器 Advice getAdvice(); // 这个有点意思:Spring所有的实现类都是return true(官方说暂时还没有应用到) // 注意:生成的Advisor是单例还是多例不由isPerInstance()的返回结果决定,而由自己在定义bean的时候控制 // 理解:和类共享(per-class)或基于实例(per-instance)相关 类共享:类比静态变量 实例共享:类比实例变量 boolean isPerInstance(); }
它的继承体系主要有如下两个:PointcutAdvisor和IntroductionAdvisor
IntroductionAdvisor与PointcutAdvisor最本质上的区别就是,IntroductionAdvisor只能应用于类级别的拦截,只能使用Introduction型的Advice。
而不能像PointcutAdvisor那样,可以使用任何类型的Pointcut,以及几乎任何类型的Advice。
PointcutAdvisor:和切点有关的Advisor
顾名思义,它和Pointcu有关。在上一篇博文:【小家Spring】Spring AOP核心类Pointcut解析,对PointcutExpression切点表达式解析原理分析(以AspectJExpressionPointcut为例)
其实我们已经介绍了好几个PointcutAdvisor。比如:RegexpMethodPointcutAdvisor和NameMatchMethodPointcutAdvisor,它哥俩都位于org.springframework.aop.support此包。当然还要介绍过AspectJExpressionPointcutAdvisor…
PointcutAdvisor它的实现类非常的多:
public interface PointcutAdvisor extends Advisor { Pointcut getPointcut(); }
AbstractPointcutAdvisor:抽象实现
// 实现了 Ordered接口 public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable { // 调用者可以手动来指定Order public void setOrder(int order) { this.order = order; } @Override public int getOrder() { if (this.order != null) { return this.order; } // 若调用者没有指定Order,那就拿advice的order为准(若有),否则LOWEST_PRECEDENCE表示最后执行 Advice advice = getAdvice(); if (advice instanceof Ordered) { return ((Ordered) advice).getOrder(); } return Ordered.LOWEST_PRECEDENCE; } // Spring还没有使用该属性 永远返回true了 @Override public boolean isPerInstance() { return true; } ... }
AbstractGenericPointcutAdvisor 一般的、通用的PointcutAdvisor
public abstract class AbstractGenericPointcutAdvisor extends AbstractPointcutAdvisor { private Advice advice = EMPTY_ADVICE; public void setAdvice(Advice advice) { this.advice = advice; } @Override public Advice getAdvice() { return this.advice; } ... }
DefaultPointcutAdvisor 通用的,最强大的Advisor
它是Spring提供的通用的,也被认为是最强大的Advisor
。它可以把任意的两个Advice和Pointcut放在一起:
public class DefaultPointcutAdvisor extends AbstractGenericPointcutAdvisor implements Serializable { private Pointcut pointcut = Pointcut.TRUE; public DefaultPointcutAdvisor() { } // 若没有指定advice,默认Pointcut.TRUE,也就是说会匹配所有的方法的执行 public DefaultPointcutAdvisor(Advice advice) { this(Pointcut.TRUE, advice); } // 显然,这个构造函数式非常强大的~~ public DefaultPointcutAdvisor(Pointcut pointcut, Advice advice) { this.pointcut = pointcut; setAdvice(advice); } }
AbstractBeanFactoryPointcutAdvisor:和bean工厂有关的PointcutAdvisor
从命名也能看出来,它和BeanFactory有关。
// 实现了BeanFactoryAware接口,若在Bean容器里注册可议注入BeanFactory~~~从而访问里面的实例 public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { // 我们发现这两个都是@Nullable,所以他们脱离容器使用也是可以的 @Nullable private String adviceBeanName; @Nullable private BeanFactory beanFactory; @Nullable private transient volatile Advice advice; public void setAdviceBeanName(@Nullable String adviceBeanName) { this.adviceBeanName = adviceBeanName; } @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; // 若在Spring环境下,会给AdviceMonitor重新赋值为:getSingletonMutex() resetAdviceMonitor(); } // 此处加锁 public void setAdvice(Advice advice) { synchronized (this.adviceMonitor) { this.advice = advice; } } // 这是它最重要的方法,获取增强器 @Override public Advice getAdvice() { Advice advice = this.advice; // 非Spring环境一般手动set进来,所以就直接返回吧 if (advice != null) { return advice; } // 显然进来Spring容器环境了,bean工厂和beanName都是不能为null的 Assert.state(this.adviceBeanName != null, "'adviceBeanName' must be specified"); Assert.state(this.beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'"); // 若bean是单例的 那就没什么好说的 直接去工厂里拿出来就完事了(Advice.class) 有可能返回null哦 if (this.beanFactory.isSingleton(this.adviceBeanName)) { advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class); this.advice = advice; return advice; } // 若是多例的,就加锁 然后调用getBean()给他生成一个新的实例即可 else { synchronized (this.adviceMonitor) { //这步赋值和判断不能省~~~确保万无一失 advice = this.advice; if (advice == null) { advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class); this.advice = advice; } return advice; } } } }
DefaultBeanFactoryPointcutAdvisor:通用的BeanFactory的Advisor
这个是和Bean工厂关联的,通用的PointcutAdvisor
public class DefaultBeanFactoryPointcutAdvisor extends AbstractBeanFactoryPointcutAdvisor { private Pointcut pointcut = Pointcut.TRUE; // 若传进来为null,还是选择 Pointcut.TRUE 匹配所有 public void setPointcut(@Nullable Pointcut pointcut) { this.pointcut = (pointcut != null ? pointcut : Pointcut.TRUE); } @Override public Pointcut getPointcut() { return this.pointcut; } }
在Spring事务相关里,你会看到这个类
位于org.springframework.aop.support包内
BeanFactoryCacheOperationSourceAdvisor:和Cache有关
Spring Cache的@Cachable等注解的拦截,就是采用了它。该类位于:org.springframework.cache.interceptor,显然它和cache相关了。Jar包属于:Spring-context.jar
// @since 3.1 毕竟Spring的整个org.springframework.cache.Cache体系都是从这里开始的。(@Cacheable...等等) public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor { // 显然它最重要的是持有这个引用(Cache章节详细介绍了它) @Nullable private CacheOperationSource cacheOperationSource; // Pointcut使用的是CacheOperationSourcePointcut private final CacheOperationSourcePointcut pointcut = new CacheOperationSourcePointcut() { @Override @Nullable protected CacheOperationSource getCacheOperationSource() { return cacheOperationSource; } }; public void setCacheOperationSource(CacheOperationSource cacheOperationSource) { this.cacheOperationSource = cacheOperationSource; } public void setClassFilter(ClassFilter classFilter) { this.pointcut.setClassFilter(classFilter); } @Override public Pointcut getPointcut() { return this.pointcut; } }
AsyncAnnotationAdvisor:和@Async有关
位于包为:org.springframework.scheduling.annotation
,所属jar包为spring-context.jar
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware { // 处理异步发生的异常的==== private AsyncUncaughtExceptionHandler exceptionHandler; private Advice advice; private Pointcut pointcut; // 构造函数们 public AsyncAnnotationAdvisor() { this(null, null); } // executor:可以自己指定异步任务的执行器 // exceptionHandler:异步异常的处理器 public AsyncAnnotationAdvisor(@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) { Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2); asyncAnnotationTypes.add(Async.class); // 支持EJB的注解:@Asynchronous try { asyncAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.ejb.Asynchronous", AsyncAnnotationAdvisor.class.getClassLoader())); } catch (ClassNotFoundException ex) { // If EJB 3.1 API not present, simply ignore. } if (exceptionHandler != null) { this.exceptionHandler = exceptionHandler; } else { // SimpleAsyncUncaughtExceptionHandler:只是一个简单的logger.error的输入打印 this.exceptionHandler = new SimpleAsyncUncaughtExceptionHandler(); } // buildAdvice: new AnnotationAsyncExecutionInterceptor(executor, exceptionHandler) 它是个MethodInterceptor 环绕通知器 this.advice = buildAdvice(executor, this.exceptionHandler); // 把asyncAnnotationTypes交给buildPointcut,它最终是个ComposablePointcut,会把这两种注解都支持。union起来 或者的关系 this.pointcut = buildPointcut(asyncAnnotationTypes); } public void setTaskExecutor(Executor executor) { this.advice = buildAdvice(executor, this.exceptionHandler); } ... }