【七】Spring Boot之 自定义starter和autoconfigure

简介

  • 自动配置(auto-configuration)
    一项简化配置的功能,比如在classpath中发现有spring security的jar包,则自动创建相关的bean等

  • starters(简化依赖)
    这个比较关键,方便spring去集成各类组件,比如redis、mongodb等等。

    • core(security、aop)

    • web(web、websocket、ws、vaadin、rest、mobile)

    • template(freemarker、velocity、groovy templates、thymeleaf)

    • data(jdbc、jpa、mongodb、redis、gemfire、solr、elasticsearch)

    • database(h2、hsqldb、mysql、postgresql)

    • social(facebook、linkedin、twitter)

    • io(batch、integration、jms、amqp)

    • ops(actuator、remote shell)

一、spring-data-redis本来的自动配置怎么用:

我们只需要引入spring-boot-starter-data-redis包就可以使用redis了,不用关心其他依赖的包

这个包中会把我们需要的其他包一起引入

看spring-data-redis中源码的自定义配置

可以知道,它给redis自动配置了一些默认属性,如:

maxActive = 8
maxIdle = 8
minIdle = 0
maxWait = -1

然后我们在引入了autoconfigure和spring-boot-starter-data-redis后,这些默认配置会自动到redis的连接池配置中。如果需要修改指定值,则在application.yml中配置

spring:
  redis:
    database: 0
    host: 192.168.2.240
    password: 123123
    port: 6379
    pool:
      maxActive: 60
      maxIdle: 60
      maxWait: 3000

application.yml没有配置,则Redis的配置用源码中自动配置的属性,如果application.yml有配置,则会被application.yml中的配置覆盖。比如:没有application.yml,则maxToal=8,有application.yml,则maxActive=60

 

二、自定义starter和autoconfigure

使用场景:

工作中有接到如下需求:

1.封装apache http client ,让业务开发的组可以开箱即用,不用关心配置。(这个不介绍,类似的)

2.封装redis,让业务开发组开箱即用,不用关心连接池的配置。这里就有个问题了,spring-data-redis已经做了自动配置了,为什么还要再封装,因为spring-data-redis做的自动配置的那些属性,跟我们期待的标准配置太不一样了。

比如,我们期待的默认配置是

        private int maxIdle = 60;

        private int minIdle = 0;

        private int maxActive = 60;

        private int maxWait = 3000;

        private boolean testOnCreate = false;

        private boolean testOnBorrow = false;

        private boolean testOnReturn = false;

        private boolean testWhileIdle = true;

        private long minEvictableIdleTimeMillis = 70000;

        private long timeBetweenEvictionRunsMillis = 40000;

        private int numTestsPerEvictionRun = -1;

各个业务系统根据实际情况,自己还可以再改。

创建一个项目common-redis-spring-boot

在这个项目中创建两个modules

common-redis-spring-boot-autoconfigure

common-redis-spring-boot-starter

结构如下

1.common-redis-spring-boot

这个工程中不要引入扫描相关的注解,如@Autowire, @componet, @Service, @Controller等

这个工程主要定义子模块的需要用到的jar。

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.sid</groupId>
    <artifactId>common-redis-spring-boot</artifactId>
    <!-- 父模块必须以pom方式打包  -->
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>1.5.8.RELEASE</spring-boot.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <common-redis.springboot.verison>1.0-SNAPSHOT</common-redis.springboot.verison>
        <common-redis.version>1.0-SNAPSHOT</common-redis.version>
    </properties>

    <!-- 定义两个子模块 -->
    <modules>
        <module>common-redis-spring-boot-autoconfigure</module>
        <module>common-redis-spring-boot-starter</module>
    </modules>

    <!-- 定义子模块中需要的jar
        所有使用dependencyManagement预先定义相关的jar和版本
        保证在子类中需要使用时,只需要引入包,而不用使用版本号
     -->
    <dependencyManagement>
        <dependencies>
            <!-- spring boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>${spring-boot.version}</version>
            </dependency>

            <dependency>
                <groupId>com.lee</groupId>
                <artifactId>common-redis-spring-boot-autoconfigure</artifactId>
                <version>${common-redis.springboot.verison}</version>
            </dependency>
            <!--  common-redis 自己写的一个redis包 里面全是静态方法-->
            <dependency>
                <groupId>com.sid</groupId>
                <artifactId>common-redis</artifactId>
                <version>${common-redis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

2.common-redis-spring-boot-autoconfigure

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">

    <parent>
        <artifactId>common-redis-spring-boot</artifactId>
        <groupId>com.sid</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../../common-redis-spring-boot/pom.xml</relativePath>
    </parent>

    <properties>
    <jackson.version>2.8.10</jackson.version>
    </properties>
    <modelVersion>4.0.0</modelVersion>


    <artifactId>common-redis-spring-boot-autoconfigure</artifactId>


    <dependencies>
        <!-- @ConfigurationProperties annotation processing (metadata for IDEs)
            生成spring-configuration-metadata.json类,需要引入此类
            -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- spring-boot redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.sid</groupId>
            <artifactId>common-redis</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
            <optional>true</optional>
        </dependency>

        <!-- spring-boot 测试包 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

spring-boot-configuration-processor 的作用是编译时生成spring-configuration-metadata.json,在intellij idea中,当配置此jar相关配置属性在application.properties,你可以用ctlr+鼠标左键,IDE会跳转到你配置此属性的类中
 

MyRedisProperties.java  属性类

自动从配置文件中解析属性并生成对象

package common.redis.spring.boot.autoconfigure.properties;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
 * @program: common-redis-spring-boot
 * @description:
 * @author: Sid
 * @date: 2018-11-01 17:18
 * @since: 1.0
 **/
//注入application.yml中spring.redis开头的属性
/**
 * 通过@EnableConfigurationProperties可以将被@ConfigurationProperties注解的类生成一个bean
 * */
@ConfigurationProperties(prefix = "spring.redis")
public class MyRedisProperties {
    /**
     * Database index used by the connection factory.
     */
    private int database = 0;

    /**
     * Redis url, which will overrule host, port and password if set.
     */
    private String url;

    /**
     * Redis server host.
     */
    private String host = "localhost";

    /**
     * Login password of the redis server.
     */
    private String password;

    /**
     * Redis server port.
     */
    private int port = 6379;

    /**
     * Enable SSL.
     */
    private boolean ssl;

    /**
     * Connection timeout in milliseconds.
     */
    private int timeout;

    private Pool pool  = new Pool();

    private Sentinel sentinel;

    private Cluster cluster;

    public int getDatabase() {
        return this.database;
    }

    public void setDatabase(int database) {
        this.database = database;
    }

    public String getUrl() {
        return this.url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getHost() {
        return this.host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getPort() {
        return this.port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public boolean isSsl() {
        return this.ssl;
    }

    public void setSsl(boolean ssl) {
        this.ssl = ssl;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public int getTimeout() {
        return this.timeout;
    }

    public Sentinel getSentinel() {
        return this.sentinel;
    }

    public void setSentinel(Sentinel sentinel) {
        this.sentinel = sentinel;
    }

    public Pool getPool() {
        return this.pool;
    }

    public void setPool(Pool pool) {
        this.pool = pool;
    }

    public Cluster getCluster() {
        return this.cluster;
    }

    public void setCluster(Cluster cluster) {
        this.cluster = cluster;
    }

    /**
     * Pool properties.
     */
    public static class Pool {

        /**
         * Max number of "idle" connections in the pool. Use a negative value to indicate
         * an unlimited number of idle connections.
         */
        private int maxIdle = 60;

        /**
         * Target for the minimum number of idle connections to maintain in the pool. This
         * setting only has an effect if it is positive.
         */
        private int minIdle = 0;

        /**
         * Max number of connections that can be allocated by the pool at a given time.
         * Use a negative value for no limit.
         */
        private int maxActive = 60;

        /**
         * Maximum amount of time (in milliseconds) a connection allocation should block
         * before throwing an exception when the pool is exhausted. Use a negative value
         * to block indefinitely.
         */
        private int maxWait = 3000;

        private boolean testOnCreate = false;

        private boolean testOnBorrow = false;

        private boolean testOnReturn = false;

        private boolean testWhileIdle = true;

        private long minEvictableIdleTimeMillis = 60000;

        private long timeBetweenEvictionRunsMillis = 30000;

        private int numTestsPerEvictionRun = -1;

        public int getMaxIdle() {
            return this.maxIdle;
        }

        public void setMaxIdle(int maxIdle) {
            this.maxIdle = maxIdle;
        }

        public int getMinIdle() {
            return this.minIdle;
        }

        public void setMinIdle(int minIdle) {
            this.minIdle = minIdle;
        }

        public int getMaxActive() {
            return this.maxActive;
        }

        public void setMaxActive(int maxActive) {
            this.maxActive = maxActive;
        }

        public int getMaxWait() {
            return this.maxWait;
        }

        public void setMaxWait(int maxWait) {
            this.maxWait = maxWait;
        }

        public boolean getTestOnCreate() {
            return testOnCreate;
        }

        public void setTestOnCreate(boolean testOnCreate) {
            this.testOnCreate = testOnCreate;
        }

        public boolean getTestOnBorrow() {
            return testOnBorrow;
        }

        public void setTestOnBorrow(boolean testOnBorrow) {
            this.testOnBorrow = testOnBorrow;
        }

        public boolean getTestOnReturn() {
            return testOnReturn;
        }

        public void setTestOnReturn(boolean testOnReturn) {
            this.testOnReturn = testOnReturn;
        }

        public boolean getTestWhileIdle() {
            return testWhileIdle;
        }

        public void setTestWhileIdle(boolean testWhileIdle) {
            this.testWhileIdle = testWhileIdle;
        }

        public long getMinEvictableIdleTimeMillis() {
            return minEvictableIdleTimeMillis;
        }

        public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
            this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
        }

        public long getTimeBetweenEvictionRunsMillis() {
            return timeBetweenEvictionRunsMillis;
        }

        public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
            this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
        }

        public int getNumTestsPerEvictionRun() {
            return numTestsPerEvictionRun;
        }

        public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
            this.numTestsPerEvictionRun = numTestsPerEvictionRun;
        }
    }

    /**
     * Cluster properties.
     */
    public static class Cluster {

        /**
         * Comma-separated list of "host:port" pairs to bootstrap from. This represents an
         * "initial" list of cluster nodes and is required to have at least one entry.
         */
        private List<String> nodes;

        /**
         * Maximum number of redirects to follow when executing commands across the
         * cluster.
         */
        private Integer maxRedirects;

        public List<String> getNodes() {
            return this.nodes;
        }

        public void setNodes(List<String> nodes) {
            this.nodes = nodes;
        }

        public Integer getMaxRedirects() {
            return this.maxRedirects;
        }

        public void setMaxRedirects(Integer maxRedirects) {
            this.maxRedirects = maxRedirects;
        }

    }

    /**
     * Redis sentinel properties.
     */
    public static class Sentinel {

        /**
         * Name of Redis server.
         */
        private String master;

        /**
         * Comma-separated list of host:port pairs.
         */
        private String nodes;

        public String getMaster() {
            return this.master;
        }

        public void setMaster(String master) {
            this.master = master;
        }

        public String getNodes() {
            return this.nodes;
        }

        public void setNodes(String nodes) {
            this.nodes = nodes;
        }

    }
}

RedisAutoConfig.java  自动配置类

package common.redis.spring.boot.autoconfigure;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.fastjson.JSON;
import common.redis.RedisUtil;
import common.redis.spring.boot.autoconfigure.properties.MyRedisProperties;
import common.redis.spring.boot.autoconfigure.properties.MyRedisProperties.Sentinel;
import common.redis.spring.boot.autoconfigure.properties.MyRedisProperties.Cluster;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;


/**
 * @program: common-redis-spring-boot
 * @description:
 * @author: Sid
 * @date: 2018-11-01 17:02
 * @since: 1.0
 **/
@Configuration  //定义配置类
@AutoConfigureBefore(RedisAutoConfiguration.class)
@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class })
@EnableConfigurationProperties(MyRedisProperties.class)
public class RedisAutoConfig {

    /**
     * Redis connection configuration.
     */
    @Configuration
    @ConditionalOnClass(GenericObjectPool.class)
    protected static class RedisConnectionConfiguration {

        private final MyRedisProperties properties;

        private final RedisSentinelConfiguration sentinelConfiguration;

        private final RedisClusterConfiguration clusterConfiguration;

        public RedisConnectionConfiguration(MyRedisProperties properties,
                                            ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration,
                                            ObjectProvider<RedisClusterConfiguration> clusterConfiguration) {
            this.properties = properties;
            this.sentinelConfiguration = sentinelConfiguration.getIfAvailable();
            this.clusterConfiguration = clusterConfiguration.getIfAvailable();
        }

        @Bean
        @ConditionalOnMissingBean(RedisConnectionFactory.class)
        public JedisConnectionFactory redisConnectionFactory()  {
            return applyProperties(createJedisConnectionFactory());
        }

        protected final JedisConnectionFactory applyProperties(JedisConnectionFactory factory) {
            configureConnection(factory);
            if (this.properties.isSsl()) {
                factory.setUseSsl(true);
            }
            factory.setDatabase(this.properties.getDatabase());
            if (this.properties.getTimeout() > 0) {
                factory.setTimeout(this.properties.getTimeout());
            }
            return factory;
        }

        private void configureConnection(JedisConnectionFactory factory) {
            if (StringUtils.hasText(this.properties.getUrl())) {
                configureConnectionFromUrl(factory);
            }
            else {
                factory.setHostName(this.properties.getHost());
                factory.setPort(this.properties.getPort());
                if (this.properties.getPassword() != null) {
                    factory.setPassword(this.properties.getPassword());
                }
            }
        }

        private void configureConnectionFromUrl(JedisConnectionFactory factory) {
            String url = this.properties.getUrl();
            if (url.startsWith("rediss://")) {
                factory.setUseSsl(true);
            }
            try {
                URI uri = new URI(url);
                factory.setHostName(uri.getHost());
                factory.setPort(uri.getPort());
                if (uri.getUserInfo() != null) {
                    String password = uri.getUserInfo();
                    int index = password.lastIndexOf(":");
                    if (index >= 0) {
                        password = password.substring(index + 1);
                    }
                    factory.setPassword(password);
                }
            }
            catch (URISyntaxException ex) {
                throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url,
                        ex);
            }
        }

        protected final RedisSentinelConfiguration getSentinelConfig() {
            if (this.sentinelConfiguration != null) {
                return this.sentinelConfiguration;
            }
            Sentinel sentinelProperties = this.properties.getSentinel();
            if (sentinelProperties != null) {
                RedisSentinelConfiguration config = new RedisSentinelConfiguration();
                config.master(sentinelProperties.getMaster());
                config.setSentinels(createSentinels(sentinelProperties));
                return config;
            }
            return null;
        }

        /**
         * Create a {@link RedisClusterConfiguration} if necessary.
         * @return {@literal null} if no cluster settings are set.
         */
        protected final RedisClusterConfiguration getClusterConfiguration() {
            if (this.clusterConfiguration != null) {
                return this.clusterConfiguration;
            }
            if (this.properties.getCluster() == null) {
                return null;
            }
            Cluster clusterProperties = this.properties.getCluster();
            RedisClusterConfiguration config = new RedisClusterConfiguration(
                    clusterProperties.getNodes());

            if (clusterProperties.getMaxRedirects() != null) {
                config.setMaxRedirects(clusterProperties.getMaxRedirects());
            }
            return config;
        }

        private List<RedisNode> createSentinels(Sentinel sentinel) {
            List<RedisNode> nodes = new ArrayList<RedisNode>();
            for (String node : StringUtils.commaDelimitedListToStringArray(sentinel.getNodes())) {
                try {
                    String[] parts = StringUtils.split(node, ":");
                    Assert.state(parts.length == 2, "Must be defined as 'host:port'");
                    nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));
                }
                catch (RuntimeException ex) {
                    throw new IllegalStateException(
                            "Invalid redis sentinel " + "property '" + node + "'", ex);
                }
            }
            return nodes;
        }

        private JedisConnectionFactory createJedisConnectionFactory() {
            JedisPoolConfig poolConfig = this.properties.getPool() != null
                    ? jedisPoolConfig() : new JedisPoolConfig();

            if (getSentinelConfig() != null) {
                return new JedisConnectionFactory(getSentinelConfig(), poolConfig);
            }
            if (getClusterConfiguration() != null) {
                return new JedisConnectionFactory(getClusterConfiguration(), poolConfig);
            }
            return new JedisConnectionFactory(poolConfig);
        }

        private JedisPoolConfig jedisPoolConfig() {
            JedisPoolConfig config = new JedisPoolConfig();
            MyRedisProperties.Pool props = this.properties.getPool();
            config.setMaxTotal(props.getMaxActive());
            config.setMaxIdle(props.getMaxIdle());
            config.setMinIdle(props.getMinIdle());
            config.setMaxWaitMillis(props.getMaxWait());

            //sid since1.0 允许用户自定义这几个属性
            config.setTestOnCreate(props.getTestOnCreate());
            config.setTestOnBorrow(props.getTestOnBorrow());
            config.setTestOnReturn(props.getTestOnReturn());
            config.setTestWhileIdle(props.getTestWhileIdle());
            config.setMinEvictableIdleTimeMillis(props.getMinEvictableIdleTimeMillis());
            config.setTimeBetweenEvictionRunsMillis(props.getTimeBetweenEvictionRunsMillis());
            config.setNumTestsPerEvictionRun(props.getNumTestsPerEvictionRun());


            return config;
        }

    }

    /**
     * Standard Redis configuration.
     */
    @Configuration
    protected static class RedisConfiguration {

        @Bean
        @ConditionalOnMissingBean(name = "redisTemplate")
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
            RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
            template.setConnectionFactory(redisConnectionFactory);

            template.setKeySerializer(new StringRedisSerializer());
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
            template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
            template.afterPropertiesSet();
            return template;
        }

        @Bean
        @ConditionalOnMissingBean(StringRedisTemplate.class)
        public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }

    }

    @Bean
    @ConditionalOnBean(RedisTemplate.class)
    public RedisUtilConfig redisUtilConfig() {
        return new RedisUtilConfig();
    }

    public class RedisUtilConfig {
        private  final Logger logger = LoggerFactory.getLogger(RedisUtilConfig.class);
        @Autowired
        private RedisTemplate redisTemplate;

        @PostConstruct
        public void afterPropertiesSet() {
            //往com.sid.common.redis中注入,这里面封装了各种静态方法。
            RedisUtil.init(redisTemplate);
            JedisConnectionFactory connectionFactory = (JedisConnectionFactory) redisTemplate.getConnectionFactory();
            logger.info("redisTemplate-->JedisConnectionFactory-->PoolConfig-->{}", JSON.toJSONString(connectionFactory.getPoolConfig(), true));
        }
    }
}

注解介绍

@Configuration:定义配置类

@EnableConfigurationProperties:属性类

@AutoConfigureAfter: 自动配置应在XXX的自动配置类之后应用。

@AutoConfigureBefore: 自动配置应在XXX的自动配置类之前应用

@AutoConfigureOrder:定义配置类执行的顺序

@ConditionalOnBean:当容器里有指定的Bean 时才生成

 

@ConditionalOnMissingBean:当容器里没有指定Bean 时才生成

@ConditionalOnClass:当类路径下有指定的类时才生成

@ConditionalOnMissingClass:当类路径下没有指定的类时才生成

@ConditionalOnExpression:基于SpEL 表达式作为判断条件。

@ConditionalOnJava:基于JVM 版本作为判断条件。

@ConditionalOnJndi:在JNDI存在的条件下查找指定的位置。

@ConditionalOnProperty:指定的属性是否有指定的值。

@ConditionalOnResource:类路径是否有指定的值。

@ConditionalOnSingleCandidate:当指定Bean 在容器中只有一个,或者虽然有多个但是指定首选的Bean。

@ConditionalOnWebApplication:当前项目是Web 项目的条件下。

@ConditionalOnNotWebApplication:当前项目不是Web 项目的条件下。

 

 

 spring.factories

src/resources/META-INF/spring.factories: 
配置RedisAutoConfig在此文件,则spring boot会自动生成初始化此类

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
common.redis.spring.boot.autoconfigure.RedisAutoConfig

3.common-redis-spring-boot-starter

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">

    <parent>
        <artifactId>common-redis-spring-boot</artifactId>
        <groupId>com.sid</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../../common-redis-spring-boot/pom.xml</relativePath>
    </parent>

    <modelVersion>4.0.0</modelVersion>


    <artifactId>common-redis-spring-boot-starter</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.sid</groupId>
            <artifactId>common-redis-spring-boot-autoconfigure</artifactId>
        </dependency>

        <dependency>
            <groupId>com.sid</groupId>
            <artifactId>common-redis</artifactId>
        </dependency>

    </dependencies>


</project>

4.common-redis

common-redis包中大致代码

public class RedisUtil  {

    /**
    * @Description: 这个redisTemplate 自动配置了连接池
     * maxIdle = 60
     * maxActive = 60
     * maxWait = 3000
     *
     * 默认使用序列化:
     *             template.setKeySerializer(new StringRedisSerializer());
     *             template.setHashKeySerializer(new StringRedisSerializer());
     *             template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
     *             template.setHashValueSerializer(new       GenericJackson2JsonRedisSerializer());
    * @Author: Sid
    * @Date: 2018-11-08 15:16
    * @since: 1.0
    */
    private static RedisTemplate redisTemplate;

    private static final AtomicBoolean init = new AtomicBoolean(false);

    public static void init(RedisTemplate redisTemplate) {
        if (init.compareAndSet(false, true)) {
            RedisUtil.redisTemplate = redisTemplate;
        }
    }


    public static<V> V get(String key) {
        return (V)redisTemplate.opsForValue().get(key);
    }

    public static <V>  void set(String key ,V value){
        redisTemplate.opsForValue().set(key,value);
    }
}

5.测试

新建一个项目,引入common-redis-spring-boot-starter包

然后直接使用common-redis中的RedisUtil

 ModelTest modelTest = new ModelTest();
 modelTest.setName("小李");
 modelTest.setAge(27);

 RedisUtil.set("common-redis:test:modelTest1",modelTest);
 RedisUtil.set("common-redis:test:string1","测试");

 RedisUtil.get("common-redis:test:string1");

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值