【源码】Spring AOP 5 Advisor

前言

AdvisorSpring AOPAdvicePointcut 的抽象,可以理解为“执行通知者”,一个 Pointcut (一般对应方法)和用于“增强”它的 Advice 共同组成这个方法的一个 Advisor

Advisor

public interface Advisor {

	// 一个空的 Advice 
	Advice EMPTY_ADVICE = new Advice() {};

	// 获取 Advice 
	Advice getAdvice();

	boolean isPerInstance();

}

顶级接口,声明了获取 Advice 的方法

PointcutAdvisor

public interface PointcutAdvisor extends Advisor {

	Pointcut getPointcut();
}

提供 Pointcut 的获取方法

AbstractPointcutAdvisor

public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable {

	// ...
	
}

最通用的抽象,实现了 Ordered 接口,AdvicePointcut 交给子类发挥

AbstractGenericPointcutAdvisor
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;
	}
}

通用抽象,暴露 setAdvice 方法,其子类可以专注于提供或者构造不同的 MethodMatcher,比如:

  • RegexpMethodPointcutAdvisor 根据传入的 patterns 构造 JdkRegexpMethodPointcut
  • AspectJExpressionPointcutAdvisor 提供 AspectJExpressionPointcut 来匹配传入的 AspectJ 表达式
  • NameMatchMethodPointcutAdvisor 提供 NameMatchMethodPointcut 来匹配传入的 mappedName 方法名,同时支持指定 ClassFilter
AbstractBeanFactoryPointcutAdvisor
public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {

	@Nullable
	private String adviceBeanName;

	@Nullable
	private BeanFactory beanFactory;

	@Nullable
	private transient volatile Advice advice;

	// ...

	@Override
	public Advice getAdvice() {
		// 缓存
		Advice advice = this.advice;
		if (advice != null) {
			return advice;
		}

		// 如果是单例直接从 bean工厂 获取
		if (this.beanFactory.isSingleton(this.adviceBeanName)) {
			advice = this.beanFactory.getBean(this.adviceBeanName, Advice.class);
			this.advice = advice;
			return advice;
		}
		else {
			// ...
		}
	}

	// 略

}
  • 基于提供的 adviceBeanName 从容器中获取 Advice
  • 子类提供具体的 Pointcut,事务实现的 BeanFactoryTransactionAttributeSourceAdvisor、缓存实现的 BeanFactoryCacheOperationSourceAdvisor 都是它的子类,在对应的文章会具体了解

StaticMethodMatcherPointcutAdvisor

public abstract class StaticMethodMatcherPointcutAdvisor extends StaticMethodMatcherPointcut
		implements PointcutAdvisor, Ordered, Serializable {

	private Advice advice = EMPTY_ADVICE;

	// ...

	// 构造方法接受一个 Advice 
	public StaticMethodMatcherPointcutAdvisor(Advice advice) {
		Assert.notNull(advice, "Advice must not be null");
		this.advice = advice;
	}

	// 接受一个 Advice
	public void setAdvice(Advice advice) {
		this.advice = advice;
	}
	
	// ...

	// 本身就是一个 StaticMethodMatcherPointcut
	@Override
	public Pointcut getPointcut() {
		return this;
	}

}

AOP 的实现中已经不止一次见到这种接口组合实现的设计模式了:

  • MethodInterceptor 组合 BeforeAdviceMethodBefreAdviceIntercpetorinvoke 驱动整个拦截链的调用并组合 BeforeAdvice 的通知逻辑
  • StaticMethodMatcher 组合 PointcutStaticMethodMatcherPointcut,借此获得 ClassFilter 的能力,子类专注于实现 match 逻辑
  • StaticMethodMatcherPointcut 组合 PointcutAdvisorStaticMethodMatcherPointcutAdvisor,借此获取 Advice 的能力,子类同样专注于实现 match 逻辑,跟 AbstractGenericPointcutAdvisor 类似,只是后者专注于提供一个具体的 Pointcut
示例实现 demo
public class StaticMethodMatcherPointcutAdvisorDemo extends StaticMethodMatcherPointcutAdvisor {

    // 实现 match 逻辑
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        return true;
    }

    @Test
    public void test() {
        StaticMethodMatcherPointcutAdvisorDemo demo = new StaticMethodMatcherPointcutAdvisorDemo();

        // 作为一个 Pointcut 可以暴露 ClassFilter 的能力
        demo.setClassFilter(clazz -> true);

        // 作为一个 PointcutAdvisor 可以暴露 Advice 的能力
        demo.setAdvice(new MethodBeforeAdviceInterceptor((
                (method, args, target) -> System.out.println("before"))));
        
        // MethodMatcher 的能力
        demo.matches(null, null);
    }
}

总结

整体上,我认为可以理解成 Advisor = Pointcut + Advice,聚焦于它的 Advisor#getAdvicePointcutAdvisor#getPointut 的实现即可

上一篇:【源码】Spring AOP 4 Pointcut
下一篇:【源码】Spring AOP 6 AspectInstanceFactory

参考

【小家Spring】Spring AOP之Advisor、PointcutAdvisor、IntroductionAdvisor、IntroductionInterceptor(引介增强)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值