上两篇将到了springboot自动配置和条件注解是如何实现,这篇在前两篇的基础上自己实现一个springboot的自动配置,用到条件注解。
需求:加入自己手写的jar。直接就可以使用StringRedisTemplate。
1.新建一个maven项目,pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.share1024</groupId>
<artifactId>redis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>redis</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
新建类RedisProperties.java
package com.share1024;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author : yesheng
* @Description :
* @Date : 2018/2/26
*/
@ConfigurationProperties(prefix = "custom.redis")
public class RedisProperties {
private int maxTotal;
private int maxIdle;
private long maxWait;
private String host;
private int port = 6379;
private int timeout;
public int getMaxTotal() {
return maxTotal;
}
public void setMaxTotal(int maxTotal) {
this.maxTotal = maxTotal;
}
public int getMaxIdle() {
return maxIdle;
}
public void setMaxIdle(int maxIdle) {
this.maxIdle = maxIdle;
}
public long getMaxWait() {
return maxWait;
}
public void setMaxWait(long maxWait) {
this.maxWait = maxWait;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
在这里我们用到了@ConfigurationProperties(prefix = “custom.redis”),也就是将我们的application.yml/application.properties中的配置以custom.redis开头的配置。
也就是将properties转化成bean
我们使用配置常量,可以用@Value,或者Environment来获取
我们redis的常量配置已经写好。
新建类RedisAutoConfiguration.java
package com.share1024;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
/**
* @author : yesheng
* @Description :
* @Date : 2018/2/26
*/
@Configuration
@ConditionalOnClass({RedisTemplate.class, Jedis.class})
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnProperty(prefix = "custom.redis",name = "host")
public class RedisAutoConfiguration {
@Bean
public StringRedisTemplate stringRedisTemplate(JedisConnectionFactory jedisConnectionFactory){
StringRedisTemplate redisTemplate = new StringRedisTemplate();
redisTemplate.setConnectionFactory(jedisConnectionFactory);
return redisTemplate;
}
@Bean
public JedisPoolConfig jedisPoolConfig(RedisProperties redisProperties){
JedisPoolConfig poolConfig = new JedisPoolConfig();
if(redisProperties.getMaxTotal() !=0){
poolConfig.setMaxTotal(redisProperties.getMaxTotal());
}
if(redisProperties.getMaxIdle() !=0){
poolConfig.setMaxIdle(redisProperties.getMaxIdle());
}
if(redisProperties.getMaxWait()!=0){
poolConfig.setMaxWaitMillis(redisProperties.getMaxWait());
}
return poolConfig;
}
@Bean
public JedisConnectionFactory jedisConnectionFactory(JedisPoolConfig jedisPoolConfig,RedisProperties redisProperties){
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig);
jedisConnectionFactory.setHostName(redisProperties.getHost());
jedisConnectionFactory.setPort(redisProperties.getPort());
if(redisProperties.getTimeout() !=0){
jedisConnectionFactory.setTimeout(redisProperties.getTimeout());
}
return jedisConnectionFactory;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
@ConditionalOnClass({RedisTemplate.class, Jedis.class})
这个类要注册到容器中,在项目上下文中必须等找到RedisTemplate.class,Jedis.class,没有这两个类就不进行配置。
@EnableConfigurationProperties(RedisProperties.class)
使@ConfigurationProperties注解生效
@ConditionalOnProperty(prefix = “custom.redis”,name = “host”)
这个就是我们的application.properties中custom.redis.host必须要有,没有就不进行配置。
文件中的3个@Bean,就是当该自动配置类,满足上面的@ConditionalOnClass({RedisTemplate.class, Jedis.class})
和@ConditionalOnProperty(prefix = “custom.redis”,name = “host”),就会将该类进行注册到spring容器中,并且会将该类下的@Bean全部注册到容器中。
这样我们就可以直接使用StringRedisTemplate
在resources目录下新建META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.share1024.RedisAutoConfiguration
- 1
- 2
上上篇讲解了@EnableAutoConfiguration使用了EnableAutoConfigurationImportSelector.class。整个流程再梳理一遍。
ConfigurationClassPostProcessor在生命周期中回去扫描@Component.
然后递归的取扫描该类中的@ImportResource,@PropertySource,@ComponentScan,@Bean,@Import。一直处理完。
@EnableAutoConfiguration
使用了@Import(EnableAutoConfigurationImportSelector.class),会去扫描META-INF/spring.factories
所有的org.springframework.boot.autoconfigure.EnableAutoConfiguration。进行进一步的扫描。
完成。
mvn clean install
- 1
新建新的项目。引入刚刚打包的项目
@Autowired
private StringRedisTemplate redisTemplate;
- 1
- 2
完成,就是这么简单。
很多时候我们要扩展spring的功能也可以从这个方向下手,例如携程的apollo框架也是这样,大家有兴趣可以去研究下。
前段时间springCloud研究完,很多人说源码看不懂,我说很简单啊,其实springcloud看不懂的就是不懂springboot源码。特别是我前面两篇的东西。有机会分析下springcloud源码把。