All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ideaaedi.extspringcache.parser.ExtCacheChecker Maven / Gradle / Ivy

The newest version!
package com.ideaaedi.extspringcache.parser;


import com.ideaaedi.extspringcache.EnableExtCache;
import com.ideaaedi.extspringcache.annotation.CaffeineOop;
import com.ideaaedi.extspringcache.annotation.ExtCacheable;
import com.ideaaedi.extspringcache.annotation.ExtCacheableOop;
import com.ideaaedi.extspringcache.annotation.RedisOop;
import com.ideaaedi.extspringcache.support.ExtCacheAroundHandlerAdvice;
import com.ideaaedi.extspringcache.support.ExtCacheHelper;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;

import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Collection;
import java.util.Set;

import static com.ideaaedi.extspringcache.support.ExtCacheHelper.LOG_PREFIX;

/**
 * ext-cache检查器
 *
 * @author JustryDeng
 * @since 2020/11/8 5:05:09
 */
public class ExtCacheChecker implements ExtCacheInitParserBeanPostProcessor, ApplicationContextAware {
    
    public static final String BEAN_NAME = "extCacheChecker";
    
    private ApplicationContext applicationContext;
    
    /**
     * 切面优先级检查
     * 

* 注: ext-spring-cache的优先级必须比ExtCacheAroundHandlerAdvice的优先级低, * 否者{@link ExtCacheHelper#determineExtCacheOop}中 * Stack stack = SafeContainer.THREAD_LOCAL_CACHE_COUNTER.get();拿到的就是null */ @Override @SuppressWarnings("NullableProblems") public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { Class clazz = bean.getClass(); EnableExtCache annotation = AnnotationUtils.findAnnotation(clazz, EnableExtCache.class); if (annotation == null) { return bean; } int springCacheProxyOrder = annotation.order(); // ext-spring-cache的优先级必须比ExtCacheAroundHandlerAdvice的优先级低 Assert.isTrue(ExtCacheAroundHandlerAdvice.ORDER < springCacheProxyOrder, LOG_PREFIX + "ext-spring-cache proxy's priority({@link EnableExtCache#order}) must below " + "ExtCacheAroundHandlerAdvice's priority({@link ExtCacheAroundHandlerAdvice#getOrder})"); return bean; } /** * 校验cacheName不能为空 * * @param extCacheable * 前@ExtCacheable信息 * @param clazz * 被当前@ExtCacheable标注的方法所在的类 * @param method * 被当前@ExtCacheable标注的方法 */ public void checkCacheNameNonEmpty(@NonNull ExtCacheable extCacheable, Class clazz, Method method) { String[] cacheNames = extCacheable.cacheNames(); Assert.isTrue(!ArrayUtils.isEmpty(cacheNames), String.format(LOG_PREFIX + " cacheNames cannot be empty, config at class[%s] method[%s]", clazz.getName(), method.getName())); } /** * 校验redis设置的过期时间不能为负 * * @param oop * ExtCacheable对应的参数模型 */ public void checkRedisAnnotationInfo(ExtCacheableOop oop) { RedisOop redisOop = oop.getRedis(); Duration duration = Duration.of(redisOop.getExpireTime(), redisOop.getTimeUnit()); Assert.isTrue(!(duration.isNegative() || duration.isZero()), String.format(LOG_PREFIX + " redis expireTime cannot be " + "negative or zero(curr duration is [%s]), config at class[%s] method[%s]", duration.toString(), oop.getClazz().getName(), oop.getMethod().getName())); } /** * 校验caffeine设置的过期时间不能为负 * * @param oop * ExtCacheable对应的参数模型 */ public void checkCaffeineAnnotationInfo(ExtCacheableOop oop) { CaffeineOop caffeine = oop.getCaffeine(); // 过期时间必要要为正 Duration duration = Duration.of(caffeine.getExpireTime(), caffeine.getTimeUnit()); Assert.isTrue(!(duration.isNegative() || duration.isZero()), String.format(LOG_PREFIX + " caffeine expireTime cannot be " + "negative or zero(curr duration is [%s]), config at class[%s] method[%s]", duration.toString(), oop.getClazz().getName(), oop.getMethod().getName())); // maximumSize和maximumWeight不能同时小于等于0 long maximumSize = caffeine.getMaximumSize(); long maximumWeight = caffeine.getMaximumWeight(); boolean maximumSizeIsLegal = maximumSize > 0; boolean maximumWeightIsLegal = maximumWeight > 0; Assert.isTrue(maximumSizeIsLegal || maximumWeightIsLegal, String.format(LOG_PREFIX + " maximumSize and maximumWeight" + "cannot less than or equal to 0 at the same time, config at class[%s] method[%s]", oop.getClazz().getName(), oop.getMethod().getName())); // 如果启用了maximumWeight的话(即: maximumSize<0 && maximumWeight > 0), 那么容器中需要有指定name的bean存在才行 if (!maximumSizeIsLegal) { String weigher4MaximumWeight = caffeine.getWeigher4MaximumWeight(); if (!applicationContext.containsBean(weigher4MaximumWeight)) { throw new IllegalArgumentException(String.format(LOG_PREFIX + " cannot find bean[%s] from " + "spring-context, config at class[%s] method[%s]", weigher4MaximumWeight, oop.getClazz().getName(), oop.getMethod().getName())); } } // 如果启用了refreshAfterWrite的话(即:refreshAfterWrite > 0), 那么容器中需要有指定name的bean存在才行 int refreshAfterWrite = caffeine.getRefreshAfterWrite(); if (refreshAfterWrite > 0) { String cacheLoader4Refresh = caffeine.getCacheLoader4Refresh(); if (!applicationContext.containsBean(cacheLoader4Refresh)) { throw new IllegalArgumentException(String.format(LOG_PREFIX + " cannot find bean[%s] from " + "spring-context, config at class[%s] method[%s]", cacheLoader4Refresh, oop.getClazz().getName(), oop.getMethod().getName())); } } } /** * 校验useTemplateName是否合法 *

* P.S. 注解上指定的useTemplateName, 在容器中必须有对应的RedisTemplate, 否者抛出异常,使启动失败。 * * @param redisTemplateNameSet * 容器中所有可用的RedisTemplate bean-name * @param useTemplateName * 开发同学指定的RedisTemplate bean-name * @param oopCollection * 所有指定RedisTemplate bean-name为useTemplateName的ExtCacheableOop集合 */ public void validRedisTemplateName(Set redisTemplateNameSet, String useTemplateName, Collection oopCollection) { if (redisTemplateNameSet.contains(useTemplateName)) { return; } StringBuilder sb = new StringBuilder(64); for (ExtCacheableOop co : oopCollection) { sb.append(String.format("\n\t### see class[%s], method[%s]", co.getClazz().getName(), co.getMethod().getName())); } throw new IllegalArgumentException( String.format(LOG_PREFIX + "there is no any RedisTemplate(or its sub-class) match bean-name [%s]. %s", useTemplateName, sb) ); } @Override public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy