Spring 由缓存切点驱动的通知者

Spring 缓存通知者和切点

缓存切点

/**
 *	Spring 核心切点抽象
 */
public interface Pointcut {

	/**
	 *	类过滤器,当前切点是否需要织入在指定的类上
	 */
	ClassFilter getClassFilter();

	/**
	 *	方法匹配器,当前切点是否需要织入在指定的方法上
	 */
	MethodMatcher getMethodMatcher();

	Pointcut TRUE = TruePointcut.INSTANCE;
}

/**
 *	检查目标方法是否需要获得通知
 */
public interface MethodMatcher {

	/**
	 *	目标方法是否需要获得通知,
	 *	isRuntime() 和此方法返回 false 时,不执行通知。
	 */
	boolean matches(Method method, Class<?> targetClass);

	/**
	 *	是否需要执行运行时匹配【false 表示只需要执行静态匹配即可】
	 *	如果 isRuntime() 返回 true,则
	 *	matches(Method method, Class<?> targetClass)
	 *	&& matches(Method method, Class<?> targetClass, Object... args)
	 *	都返回 true 时才执行通知
	 */
	boolean isRuntime();

	/**
	 *	当 matches(Method method, Class<?> targetClass) 和 isRuntime() 都返回 true 时,
	 *	在通知执行前再次进行匹配
	 */
	boolean matches(Method method, Class<?> targetClass, Object... args);

	/**
	 *	匹配所有方法
	 */
	MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}

/**
 *	不关心运行时参数的静态方法匹配器
 */
public abstract class StaticMethodMatcher implements MethodMatcher {
	@Override
	public final boolean isRuntime() {
		return false;
	}

	@Override
	public final boolean matches(Method method, Class<?> targetClass, Object... args) {
		// should never be invoked because isRuntime() returns false
		throw new UnsupportedOperationException("Illegal MethodMatcher usage");
	}
}

/**
 *	缓存操作切点抽象
 */
@SuppressWarnings("serial")
abstract class CacheOperationSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
	/**
	 *	目标类的指定方法是否需要通知
	 */
	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		// 排除缓存管理器
		if (CacheManager.class.isAssignableFrom(targetClass)) {
			return false;
		}
		final CacheOperationSource cas = getCacheOperationSource();
		// 存在缓存操作源 && 指定方法上能解析到缓存操作
		return cas != null && !CollectionUtils.isEmpty(cas.getCacheOperations(method, targetClass));
	}

	@Override
	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof CacheOperationSourcePointcut)) {
			return false;
		}
		final CacheOperationSourcePointcut otherPc = (CacheOperationSourcePointcut) other;
		return ObjectUtils.nullSafeEquals(getCacheOperationSource(), otherPc.getCacheOperationSource());
	}

	@Override
	public int hashCode() {
		return CacheOperationSourcePointcut.class.hashCode();
	}

	@Override
	public String toString() {
		return getClass().getName() + ": " + getCacheOperationSource();
	}

	/**
	 * Obtain the underlying {@link CacheOperationSource} (may be {@code null}).
	 * To be implemented by subclasses.
	 */
	@Nullable
	protected abstract CacheOperationSource getCacheOperationSource();
}

缓存通知者

/**
 *	持有 AOP 通知的基础接口
 */
public interface Advisor {
	/**
	 *	如果没有正确配置通知,则返回一个空通知
	 * @since 5.0
	 */
	Advice EMPTY_ADVICE = new Advice() {};

	/**
	 *	返回切面的通知
	 */
	Advice getAdvice();

	/**
	 *	此通知是否与具体的实例关联【不可共享】
	 */
	boolean isPerInstance();
}

/**
 *	由切入点驱动的通知者接口
 */
public interface PointcutAdvisor extends Advisor {
	/**
	 *	获取驱动此 Advisor 的切入点
	 */
	Pointcut getPointcut();
}

@SuppressWarnings("serial")
public abstract class AbstractPointcutAdvisor implements PointcutAdvisor, Ordered, Serializable {
	/**
	 *	此 Advisor 关联切面的顺序值:值越小,越先执行
	 */
	@Nullable
	private Integer order;

	public void setOrder(int order) {
		this.order = order;
	}

	@Override
	public int getOrder() {
		if (order != null) {
			return order;
		}
		final Advice advice = getAdvice();
		if (advice instanceof Ordered) {
			return ((Ordered) advice).getOrder();
		}
		return Ordered.LOWEST_PRECEDENCE;
	}

	@Override
	public boolean isPerInstance() {
		return true;
	}

	@Override
	public boolean equals(Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof PointcutAdvisor)) {
			return false;
		}
		final PointcutAdvisor otherAdvisor = (PointcutAdvisor) other;
		return ObjectUtils.nullSafeEquals(getAdvice(), otherAdvisor.getAdvice()) &&
				ObjectUtils.nullSafeEquals(getPointcut(), otherAdvisor.getPointcut());
	}

	@Override
	public int hashCode() {
		return PointcutAdvisor.class.hashCode();
	}
}

/**
 *	以 BeanFactory 为基础的切点通知者,通知可以配置为 BeanFactory 中的 bean。
 */
@SuppressWarnings("serial")
public abstract class AbstractBeanFactoryPointcutAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {
	/**
	 *	通知 Bean 的名称
	 */
	@Nullable
	private String adviceBeanName;
	/**
	 *	Bean 工厂
	 */
	@Nullable
	private BeanFactory beanFactory;
	/**
	 *	延迟初始化的通知对象
	 */
	@Nullable
	private transient volatile Advice advice;
	/**
	 *	锁
	 */
	private transient volatile Object adviceMonitor = new Object();

	public void setAdviceBeanName(@Nullable String adviceBeanName) {
		this.adviceBeanName = adviceBeanName;
	}

	@Nullable
	public String getAdviceBeanName() {
		return adviceBeanName;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		resetAdviceMonitor();
	}

	private void resetAdviceMonitor() {
		if (beanFactory instanceof ConfigurableBeanFactory) {
			adviceMonitor = ((ConfigurableBeanFactory) beanFactory).getSingletonMutex();
		}
		else {
			adviceMonitor = new Object();
		}
	}

	public void setAdvice(Advice advice) {
		synchronized (adviceMonitor) {
			this.advice = advice;
		}
	}

	/**
	 *	从 beanFactory 中读取通知实例
	 */
	@Override
	public Advice getAdvice() {
		Advice advice = this.advice;
		// 通知已经初始化,则直接返回
		if (advice != null) {
			return advice;
		}

		Assert.state(adviceBeanName != null, "'adviceBeanName' must be specified");
		Assert.state(beanFactory != null, "BeanFactory must be set to resolve 'adviceBeanName'");

		// 通知 bean 是单例
		if (beanFactory.isSingleton(adviceBeanName)) {
			// 依赖于 Bean 工厂提供的单例语义
			advice = beanFactory.getBean(adviceBeanName, Advice.class);
			this.advice = advice;
			return advice;
		}
		else {
			synchronized (adviceMonitor) {
				advice = this.advice;
				if (advice == null) {
					advice = beanFactory.getBean(adviceBeanName, Advice.class);
					this.advice = advice;
				}
				return advice;
			}
		}
	}

	@Override
	public String toString() {
		final StringBuilder sb = new StringBuilder(getClass().getName());
		sb.append(": advice ");
		if (adviceBeanName != null) {
			sb.append("bean '").append(adviceBeanName).append("'");
		}
		else {
			sb.append(advice);
		}
		return sb.toString();
	}
}

/**
 *	由 CacheOperationSource 驱动的 Advisor
 */
@SuppressWarnings("serial")
public class BeanFactoryCacheOperationSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
	@Nullable
	private CacheOperationSource cacheOperationSource;
	/**
	 *	缓存操作切点
	 */
	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) {
		pointcut.setClassFilter(classFilter);
	}

	@Override
	public Pointcut getPointcut() {
		return pointcut;
	}
}

posted on 2019-01-26 09:46  竺旭东  阅读(195)  评论(0编辑  收藏  举报

导航