开始
spring-boot 为什么现在这么火了,因为它解决了很多配置信息文件
实现了集成一个组件,装箱即用的效果。也就是约定大于配置。
平常工作中,我们也可以开发自己的starter包,下面以我写的一个工具包为例
需求
写一个redis的客户端spring boot工具包,同时能够实现连接 单点,哨兵,cluster。
代码已经上传至github 快速入口
使用方法
1,把我github的项目下载下来,打成jar导入到自己的maven库或者公司的私服。
2,pom引入jia,
<dependency>
<groupId>com.shrek</groupId>
<artifactId>spring-boot-redis-starter</artifactId>
<version>${shrek.version}</version>
</dependency>
3,springboot的启动类加上注解 @EnableRedis(value = RedisModeConstants.REDIS_CLUSTER)
4,application.yml加配置自己的redis配置信息,具体参考com\shrek\redis\starter\properties\RedisProperties.java
shrek:
redis:
enable: true
host: 192.168.233.106
# cluster: 192.168.89.132:6379,192.168.89.132:6380,192.168.89.132:6381,192.168.89.132:6382,192.168.89.132:6383,192.168.89.132:6384
实现
- 首先,建立一个redis-cluster,可以查看我以前的博客 快速入口
- 代码的一些关键代码。
classpath:META-INF/spring.factories文件是springboot启动时,
org.spring.framework.core.io.support.SpringFactoriesLoader会扫描的文件,
下面是RedisInitAutoConfiguraion类
@Configuration
@ConditionalOnProperty(prefix = RedisProperties.PREFIX, name = "enable", havingValue = "true")
@EnableConfigurationProperties(value = RedisProperties.class)
public class RedisInitAutoConfiguration {
/**
* 初始化 applicationContext 工具类,
* 当类继承 ApplicationContextAware ,会调用setApplicationContext
* @author 吴署
* @return
*/
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public RedisBeanUtil beanUtil() {
return new RedisBeanUtil();
}
@Bean
@ConditionalOnMissingBean(ShrekRedisTemplate.class)
public ShrekRedisTemplate easyRedisTemplate() {
return new ShrekRedisTemplate();
}
@Bean
@ConditionalOnMissingBean(JedisConnectionFactory.class)
public JedisConnectionFactory jedisConnectionFactory(RedisProperties redisProperties) {
return RedisConnectionFactoryUtil.init(redisProperties);
}
}
这个类的主要作用
1,首先这是一个配置类 @Configuration
2,指定我的读取配置类RedisProperties
3,beanUtil() 初始化applicationContext,
jedisConnectionFactory(RedisProperties redisProperties) 通过配置信息jedisConnectionFactory
shrekRedisTemplate() 客户端操作
EnableRedis.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(RedisConfigRegistrar.class)
public @interface EnableRedis {
String value() default RedisModeConstants.REDIS_SINGLE;
}
这个类是启动注解类,在springboot 启动类注解@EnableRedis(value = RedisModeConstants.REDIS_CLUSTER)
指定redis-client是cluster集群客户端,这里又@Import(RedisConfigRegistrar.class)导入了RedisConfigRegistrar类
RedisConfigRegistrar.java
RedisConfigRegistrar继承了ImportBeanDefinitionRegistrar , BeanFactoryAware,所以可以在这里
往beanfactory里注入client的Process类。
/**
* redis 配置初始化
* spring 类继承ImportBeanDefinitionRegistrar , BeanFactoryAware
* @author 吴署
*/
public class RedisConfigRegistrar implements ImportBeanDefinitionRegistrar , BeanFactoryAware{
private BeanFactory beanFactory;
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//得到启动类注解的@EnableRedis(value = RedisModeConstants.REDIS_CLUSTER)
AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(
EnableRedis.class.getName()));
//获取启动类注解的client的类型
String redisMode = attributes.getString("value");
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) this.beanFactory;
// 通过BeanDefinitionBuilder创建bean定义,
// 并注册到spring bean factory 工厂
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedisEnvironment.class);
defaultListableBeanFactory.registerBeanDefinition(RedisEnvironment.class.getName(),beanDefinitionBuilder.getBeanDefinition());
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedisAdapter.class);
defaultListableBeanFactory.registerBeanDefinition(RedisAdapter.class.getName(),beanDefinitionBuilder.getBeanDefinition());
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedisSingleProcessor.class);
defaultListableBeanFactory.registerBeanDefinition(RedisSingleProcessor.class.getName(),beanDefinitionBuilder.getBeanDefinition());
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedisClusterProcessor.class);
defaultListableBeanFactory.registerBeanDefinition(RedisClusterProcessor.class.getName(),beanDefinitionBuilder.getBeanDefinition());
beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedisSentinelProcessor.class);
defaultListableBeanFactory.registerBeanDefinition(RedisSentinelProcessor.class.getName(),beanDefinitionBuilder.getBeanDefinition());
factoryInit(redisMode);
}
/**
* 修改bean中RedisEnvironment的是否初始化属性
* 和设置bean中RedisAdapter的redis客户端类型
* @param redisMode
*/
private void factoryInit(String redisMode) {
RedisEnvironment redisEnvironment = (RedisEnvironment) this.beanFactory.getBean(RedisEnvironment.class.getName());
redisEnvironment.setRedisConnectionFactoryIsInit(Boolean.TRUE);
RedisAdapter redisAdapter = (RedisAdapter) this.beanFactory.getBean(RedisAdapter.class.getName());
redisAdapter.setRedisMode(redisMode);
}
/**
* 重写BeanFactoryAware的setBeanFactory,
* 将spring的beanFactory赋给this.beanFactory
* @param beanFactory
* @throws BeansException
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory=beanFactory;
}