• 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;
    	}
    }
    
  • 相关阅读:
    encodeURI 编码、decodeURI 解码
    JavaScript toLocaleString() 方法
    element-ui el-upload限制图片格式尺寸及图片
    vue计算属性的使用
    element级联选择器表单回显
    关于css浮动需要注意的一点
    el-tree树形结构实现自定义关联
    element UI 表格中暂无数据自定义
    vue登录流程
    vue 中表单置空简单操作
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10322618.html
Copyright © 2020-2023  润新知