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 ...
随机推荐
- 传输层协议之TCP/UDP
1.UDP UDP协议是面向无连接的,即不需要在正式传递数据前先链接双方,UDP协议只是数据报文的搬运工,不保证有序且不丢失的传递到对端,且UDP协议无任何控制流量的算法,UDP相对于TCP更加轻便. ...
- SpringBoot项目中遇到的BUG
1.启动项目的时候报错 1.Error starting ApplicationContext. To display the auto-configuration report re-run you ...
- Flask开发系列之快速入门
Flask开发系列之快速入门 文档 一个最小的应用 调试模式 路由 变量规则 构造 URL HTTP 方法 静态文件 模板渲染 访问请求数据 环境局部变量 请求对象 文件上传 Cookies 重定向和 ...
- Java动态加载类
详见:https://blog.csdn.net/zai_xia/article/details/80026325 扩展:java反射机制与动态加载类 https://www.cnblogs.com/ ...
- Linux连接外网~可以Windows与Linux互ping通~图文
我这里用的是CentOS7_1511 下载地址 http://linux.xitongxz.net:808/201603/CentOS-7-x86_64-DVD-1511.iso 选择 虚拟机左上角 ...
- python子进程模块subprocess详解
subprocess--子进程管理器一.subprocess 模块简介subprocess最早是在2.4版本中引入的.subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/错误, ...
- 2019-2020-1 20199319《Linux内核原理与分析》第二周作业
计算机是如何工作的 反汇编一个简单的C程序 1.在实验环境下,创建main.c,并进入该文件进行代码的编写 在VIM文本编辑器中编写完代码后按"Shift"+":&quo ...
- GPT-2,吓坏创造者的「深度造假写手」
简评: 今年二月份刷屏的 GPT-2 着实厉害,那个生成续写故事的例子更是效果好到吓人一跳,它到底有多厉害,本文略微讲讲.更详细的信息可参考文末 OpenAI 的博客链接. 你能从下面这两段文字里品味 ...
- Stanford CS229 Machine Learning by Andrew Ng
CS229 Machine Learning Stanford Course by Andrew Ng Course material, problem set Matlab code written ...
- 对所有的webview添加userAgent
在appdelegate中- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDicti ...