cn.godmao.redis.config.RedisAutoConfig Maven / Gradle / Ivy
The newest version!
package cn.godmao.redis.config;
import cn.godmao.redis.*;
import cn.godmao.redis.annotation.Redis;
import cn.godmao.redis.aspect.CacheAspect;
import cn.godmao.redis.codec.EntityCodec;
import org.redisson.api.*;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RedisAutoConfig extends CachingConfigurerSupport implements BeanPostProcessor {
@Autowired
private GenericApplicationContext applicationContext;
@Autowired
private RedissonClient redissonClient;
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Class> beanClass = AopUtils.getTargetClass(bean);
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
Redis annotation = field.getAnnotation(Redis.class);
if (null == annotation) {
continue;
}
String name = annotation.value();
if (ObjectUtils.isEmpty(name)) {
name = field.getName();
}
if (ObjectUtils.isEmpty(name)) {
continue;
}
final String beanName_ = "redis_####_" + name;
final Class> type_ = field.getType();
final Object object_;
final Object bean_;
if (this.applicationContext.containsBean(beanName_)) {
bean_ = this.applicationContext.getBean(beanName_, type_);
} else {
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Type actualTypeArgument = actualTypeArguments[actualTypeArguments.length - 1];
EntityCodec entityCodec = new EntityCodec(actualTypeArgument);
if (type_.isAssignableFrom(RMap.class)) {
object_ = redissonClient.getMap(name, entityCodec);
} else if (type_.isAssignableFrom(RList.class)) {
object_ = redissonClient.getList(name, entityCodec);
} else if (type_.isAssignableFrom(RSet.class)) {
object_ = redissonClient.getSet(name, entityCodec);
} else if (type_.isAssignableFrom(RKeys.class)) {
object_ = redissonClient.getKeys();
} else {
System.err.println("未知类型" + type_ + "请添加");
continue;
}
ConfigurableListableBeanFactory beanFactory = this.applicationContext.getBeanFactory();
bean_ = beanFactory.initializeBean(object_, beanName_);
beanFactory.registerSingleton(beanName_, bean_);
}
try {
field.setAccessible(true);
field.set(bean, bean_);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return bean;
}
@Bean
public RedisLockTemplate lockTemplate(RedissonClient redissonClient) {
return new RedisLockTemplate(redissonClient);
}
// @Bean
// public ExecutorService executorService(RedissonClient redissonClient) {
// return redissonClient.getExecutorService("WORK_REDIS_");
// }
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
return RedisConfig.redisTemplate(factory);
}
@Bean
public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
return RedisConfig.redisCacheManager(redisTemplate);
}
/**
* redis消息监听器
* 可以添加多个监听不同话题的redis监听器
* 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
*/
@Bean
@ConditionalOnBean(RedisListener.class)
public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory, RedisListener... listeners) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
// 订阅通道的地方
for (RedisListener listener : listeners) {
container.addMessageListener(listener, new ChannelTopic(listener.getKey()));
}
// 这个container 可以添加多个 messageLister
return container;
}
// @Bean
// @ConditionalOnBean(RedisMap.class)
// public RedisGroup redisGroup(RedisTemplate redisTemplate, RedisMap... redisMaps) {
// Map> redisGroup = new HashMap<>();
// for (RedisMap redisMap : redisMaps) {
// redisMap.init(redisTemplate);
// redisGroup.put(redisMap.getKey(), redisMap);
// }
// return new RedisGroup((Map) redisGroup);
// }
@Bean
@ConditionalOnBean(AbstractRedisMap.class)
public Map> redisMaps(RedisTemplate redisTemplate, AbstractRedisMap... redisMaps) {
Map> redisMaps_ = new HashMap<>();
for (AbstractRedisMap redisMap : redisMaps) {
redisMap.init(redisTemplate);
redisMaps_.put(redisMap.getKey(), redisMap);
}
return redisMaps_;
}
@Bean
public RedisGlobal redisGlobal(RedisTemplate redisTemplate) {
return new RedisGlobal(redisTemplate);
}
@Bean
@ConditionalOnBean(AbstractRedisValue.class)
public Map> redisValues(RedisTemplate redisTemplate, AbstractRedisValue... redisValues) {
Map> redisValues_ = new HashMap<>();
for (AbstractRedisValue redisValue : redisValues) {
redisValue.init(redisTemplate);
redisValues_.put(redisValue.getKey(), redisValue);
}
return redisValues_;
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
// 异常处理,当Redis发生异常时,打印日志,但是程序正常走
return new CacheErrorHandler() {
@Override
public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
System.err.printf("Redis occur handleCacheGetError:key -> [%s]", key);
e.printStackTrace();
}
@Override
public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
System.err.printf("Redis occur handleCachePutError:key -> [%s];value -> [%s]", key, value);
e.printStackTrace();
}
@Override
public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
System.err.printf("Redis occur handleCacheEvictError:key -> [%s]", key);
e.printStackTrace();
}
@Override
public void handleCacheClearError(RuntimeException e, Cache cache) {
System.err.println("Redis occur handleCacheClearError:");
e.printStackTrace();
}
};
}
@Bean
@DependsOn({"redisTemplate"})
public CacheAspect cacheAspect(RedisTemplate redisTemplate) {
return new CacheAspect(redisTemplate);
}
}