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

最新文章

  1. entity framework 5 批量增删改效率优化
  2. Thinkphp 3.2中字符串截取
  3. AWS CloudFormation Template
  4. 用字符串模拟两个大数相加——java实现
  5. 【转载】C++ function、bind和lambda表达式
  6. 解决VirtualBox 上的XP 蓝屏,自动重复启动
  7. wzplayer for ios 针对(mms)优化版本V1.0
  8. 静态链表实现(A-B)+(B-A)【代码】
  9. C# 返回JSON格式化统一标准
  10. 洛谷P4362 贪吃的九头龙
  11. JavaScript面试技巧(一):基础知识
  12. arch 安装准备--包管理的使用pacman
  13. Ansible之playbook的使用总结 - 运维笔记
  14. hdu1753-大明A+B-(java大数)
  15. 大数据领域两大最主流集群管理工具Ambari和Cloudera Manger
  16. hdu2176nim博弈
  17. JDK7 AutoCloseable
  18. gulp 在 angular 项目中的使用
  19. CakePHP redirect函数
  20. shell入门基础&amp;常见命令及用法

热门文章

  1. 在easyui中解决使west和center为1:1,并且拖动窗口时能够自适应变化
  2. java 内部类复习
  3. 搭建CocoaPods远程私有库
  4. MapUtils
  5. 从零开始学MySQL(一)
  6. Laravel-admin 加载视图后,blade 模板 JS 失效
  7. mariadb数据库简介
  8. 理解BurpSuit Intruder几种攻击方式
  9. id 显示用户与用户组的信息
  10. 深入理解docker