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;
}
}
Spring 由缓存切点驱动的通知者的更多相关文章
- 注释驱动的 Spring cache 缓存介绍
概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...
- [转]注释驱动的 Spring cache 缓存介绍
原文:http://www.ibm.com/developerworks/cn/opensource/os-cn-spring-cache/ 概述 Spring 3.1 引入了激动人心的基于注释(an ...
- 注释驱动的 Spring cache 缓存介绍--转载
概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...
- Spring cache 缓存
概述 Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 OSCache),而是一个对缓存使 ...
- Spring实战——缓存
缓存 提到缓存,你能想到什么?一级缓存,二级缓存,web缓存,redis-- 你所能想到的各种包罗万象存在的打着缓存旗号存在的各种技术或者实现,无非都是宣扬缓存技术的优势就是快,无需反复查询等. 当然 ...
- Spring 对缓存的抽象
Cache vs. Buffer A buffer is used traditionally as an intermediate temporary store for data between ...
- 谈谈spring的缓存
缓存到底扮演了什么角色 请移步: http://hacpai.com/article/1376986299174 在对项目进行优化的时候,我们可以主要从以下三个方面入手: 1 缓存 2 集群 3 异 ...
- Spring之缓存注解@Cacheable
https://www.cnblogs.com/fashflying/p/6908028.html https://blog.csdn.net/syani/article/details/522399 ...
- Java缓存学习之五:spring 对缓存的支持
(注意标题,Spring对缓存的支持 这里不单单指Ehcache ) 从3.1开始,Spring引入了对Cache的支持.其使用方法和原理都类似于Spring对事务管理的支持.Spring Cache ...
随机推荐
- MySQL查询最近一周(最近7天)数据
参考:https://blog.csdn.net/ouyang111222/article/details/77638826 -表结构 - CREATE TABLE `zk_score` ( `id` ...
- PHP实现无限极分类的两种方式
无限极分类说简单点就是一个类可以分成一个分子类,然后一个子类又可以分另一个子类这样无限分下去,就是好象windows可以新建一个文件夹,然后在这个文件夹里又可以建一个文件夹,PHP要实现无限极分类有两 ...
- hadoop最简伪分布式安装
本次安装运行过程使用的是Ubuntu16.04 64位+Hadoop2.5.2+jdk1.7.0_75 Notice: Hadoop2.5.2版本默认只支持64位系统 使用的jdk可以为1.7和1.8 ...
- Scala Option 从官方DOC解析
Represents optional values. Instances of Option are either an instance of scala.Some or the object N ...
- python日志汇总
1. 文件头在Linux下推荐文件头: #! /usr/bin/env python # -*- coding: utf-8 -*- 2.import导入语句 import: 一般导入第三包可以直接使 ...
- Linux crontab计划任务
1.cron计划任务的描述 cron计划任务允许用户根据“时间表”自动周期的完成任务某些任务. cron是一种system V服务,需要开启该服务才能使用. ...
- java.util.Arrays (JDK 1.7)
1.asList //返回由指定数组支持的固定大小的列表,返回的列表是可序列化的 public static <T> List<T> asList(T... a) { retu ...
- java.lang.Object类(JDK1.7)
1.Object的类方法 package java.lang; public class Object { private static native void registerNatives(); ...
- oracle数据库应用总结
1------->>>>>>>>>>>>>>>>>>>>>>> ...
- Big Data(五)关于Hadoop的HA的实践搭建
JoinNode 分布在node01,node02,node03 1.停止之前的集群 2.免密:node01,node02 node02: cd ~/.ssh ssh-keygen -t dsa -P ...