Spring Boot:通過spring-boot-starter-data-redis源碼了解starter和autoconfigure模塊


注:本文Spring Boot為2.X版本
在Spring Boot中,官方提供了spring-boot-autoconfigure包和starter包用來幫助我們簡化配置,比如之前要建一個Spring mvc項目,需要我們配置web.xml,dispatcherservlet-servlet.xml,applicationContext.xml等等。而在Spring Boot中只需要在pom中引入

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

就能完成之前所有的工作了。簡直so easy啊。
但是只會用是不行的,還要知其所以然,本文以官方的starter:spring-boot-starter-data-redis為例,從源碼層面上分析整個自動化配置的過程。以期對starter和autoconfigure這兩個Spring Boot的核心模塊進行梳理。
了解原理后,我會通過模擬spring-boot-starter-data-redis,並使用Jedis來創建一個處理redis的自定義starter:my-redis-starter。源碼下載 點我,最后會詳細說明自定義starter的創建過程。

在Spring Boot中使用默認的redis客戶端只需要
在pom.xml中引入

 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 

然后在application.properties中配置ip,密碼等必要參數

spring.redis.host=106.15.108.50
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認為空)
spring.redis.password=123456
#等等 

就可以直接在我們的業務中調用org.springframework.data.redis.core.RedisTemplate來處理緩存的相關操作了。

一.RedisTemplate的注入

讓我們先來看下RedisTemplate是如何被注入的。

1.RedisProperties

application.properties中ctrl+左擊redis的相關配置項,會打開spring-boot-autoconfigure\2.0.2.RELEASE\spring-boot-autoconfigure-2.0.2.RELEASE.jar中的RedisProperties
在這里插入圖片描述
打開org.springframework.boot.autoconfigure.data.redis.RedisProperties.class

@ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { /** * Database index used by the connection factory. */ private int database = 0; /** * Connection URL. Overrides host, port, and password. User is ignored. Example: * redis://user:password@example.com:6379 */ 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; /** * Whether to enable SSL support. */ private boolean ssl; /** * Connection timeout. */ private Duration timeout; private Sentinel sentinel; private Cluster cluster; private final Jedis jedis = new Jedis(); private final Lettuce lettuce = new Lettuce(); ...... } 

(1) @ConfigurationProperties(prefix = "spring.redis") 設置綁定屬性的前綴,然后看下前面的一些屬性,是不是很眼熟?前綴+屬性名就是之前在application.properties中配置的,如果我們沒有配置端口這種屬性,那么這里也會提供部分默認配置。
當然,只是這些是沒辦法讓Spring Boot在啟動時掃描到該類的,所以需要下一個類org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class
然后我們還能找到

private final Jedis jedis = new Jedis(); private final Lettuce lettuce = new Lettuce(); 

一般用Java操作redis用的較多幾個Java客戶端為Jedis,Redisson,Lettuce。這里可知官方提供的spring-boot-starter-data-redis底層是用Jedis/Lettuce實現的,知道了這個我們也能夠借鑒這個starter來使用其他的客戶端來實現了。

2.RedisAutoConfiguration

打開org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class

@Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { @Bean @ConditionalOnMissingBean(name = "redisTemplate") public RedisTemplate<Object, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; } } 

(1)@Configuration常見的配置注解,內部含有一個以上的@Bean,讓Spring能掃描到內部的@Bean,當然在Spring Boot中,默認只會掃描到啟動類所在包或其下級包的類,所以還會通過其他的設置來讓這個類被掃描到,這個后面會詳細說明。

@Configuration用於定義配置類,可替換xml配置文件,被注解的類內部包含有一個或多個被@Bean注解的方法,這些方法將會被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext類進行掃描,並用於構建bean定義,初始化Spring容器。

(2)@ConditionalOnClass(RedisOperations.class),當存在RedisOperations類時才會進行掃描,這個類什么時候被引入classpath的之后會提到。
(3)@EnableConfigurationProperties(RedisProperties.class)RedisProperties 類被掃描到的關鍵。這時,如果RedisAutoConfiguration被掃描到,則同時也會去掃描RedisProperties類。
(4)@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })通過@Import注解方式生成類實例並注入Spring容器。

@Import注解通過導入的方式實現把實例加入springIOC容器中

讓我們打開JedisConnectionConfiguration簡要看下

@Configuration @ConditionalOnClass({ GenericObjectPool.class, JedisConnection.class, Jedis.class }) class JedisConnectionConfiguration extends RedisConnectionConfiguration { private final RedisProperties properties; private final List<JedisClientConfigurationBuilderCustomizer> builderCustomizers; JedisConnectionConfiguration(RedisProperties properties, ObjectProvider<RedisSentinelConfiguration> sentinelConfiguration, ObjectProvider<RedisClusterConfiguration> clusterConfiguration, ObjectProvider<List<JedisClientConfigurationBuilderCustomizer>> builderCustomizers) { super(properties, sentinelConfiguration, clusterConfiguration); this.properties = properties; this.builderCustomizers = builderCustomizers .getIfAvailable(Collections::emptyList); } @Bean @ConditionalOnMissingBean(RedisConnectionFactory.class) public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException { return createJedisConnectionFactory(); } ...... } 
  • @Import注解會通過JedisConnectionConfiguration構造方法將JedisConnectionConfiguration的實例注入到Spring容器中,這里有一個RedisProperties參數,實際上就是在(3)中注入的RedisProperties,這樣JedisConnectionConfiguration就獲得了RedisProperties,也就獲得了之前我們在application.propertie中配置的redis服務器連接屬性。
  • 通過@Configuration@Bean的定義可知,會掃描到redisConnectionFactory()方法並返回實體,並注入到Spring容器,對應的類為RedisConnectionFactory。(JedisConnectionConfiguration實現了RedisConnectionFactory接口,所以可以這樣)
    @Bean @ConditionalOnMissingBean(RedisConnectionFactory.class) public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException { return createJedisConnectionFactory(); } private JedisConnectionFactory createJedisConnectionFactory() { JedisClientConfiguration clientConfiguration = getJedisClientConfiguration(); if (getSentinelConfig() != null) { return new JedisConnectionFactory(getSentinelConfig(), clientConfiguration); } if (getClusterConfiguration() != null) { return new JedisConnectionFactory(getClusterConfiguration(), clientConfiguration); } return new JedisConnectionFactory(getStandaloneConfig(), clientConfiguration); } private JedisClientConfiguration getJedisClientConfiguration() { JedisClientConfigurationBuilder builder = applyProperties( JedisClientConfiguration.builder()); RedisProperties.Pool pool = this.properties.getJedis().getPool(); if (pool != null) { applyPooling(pool, builder); } if (StringUtils.hasText(this.properties.getUrl())) { customizeConfigurationFromUrl(builder); } customize(builder); return builder.build(); } 
    ① getJedisClientConfiguration()方法,該方法從之前注入的RedisProperties中獲取了 Jedis客戶端連接池。
    createJedisConnectionFactory會根據配置的redis參數判斷用單機/哨兵/集群模式來創建JedisConnectionFactory實例。

總結:創建並注入了JedisConnectionFactory實例,JedisConnectionFactory實例中包含有Jedis的客戶端連接池,之后就能用其創建連接了。

(5)redisTemplate方法

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

終於找到注入redisTemplate的地方了= =。

  • 這是個被@Bean注解的方法,因此會被Spring掃描並注入。
  • @ConditionalOnMissingBean(name = "redisTemplate")當Spring容器中不存在RedisTemplate實例時才會進行掃描注入,很明顯是為了防止重復注入。
  • 該方法有一個RedisConnectionFactory參數。
    而我們知道(4)中redisConnectionFactory方法最后會注入一個JedisConnectionFactory實例,而JedisConnectionFactory又是繼承於RedisConnectionFactory。同志們,你們懂我的意思了吧∠( ᐛ 」∠)_。

總結:該方法會將先前注入的redisConnectionFactory賦給新建的redisTemplate實例,
然后將redisTemplate實例注入Spring容器。

但是這里出現一個問題了
開始時通過@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })注入了Lettuce和Jedis兩個連接配置實例,
而這兩個中又都已@Bean的形式注入了JedisConnectionFactoryLettuceConnectionFactory兩個實例(這兩個實例的類又都是繼承於
RedisConnectionFactory的),並且注入時都是對應RedisConnectionFactory類的。那么redisTemplate方法最后是使用哪個實例來創建RedisTemplate的呢?
在這里插入圖片描述
通過debug我們知道實際用的是LettuceConnectionFactory實例。
這么看是按照@Import中的排序來的,
這里LettuceConnectionConfiguration在前,所以會先掃描LettuceConnectionConfiguration。相關代碼

	@Bean @ConditionalOnMissingBean(RedisConnectionFactory.class) public LettuceConnectionFactory redisConnectionFactory( ClientResources clientResources) throws UnknownHostException { LettuceClientConfiguration clientConfig = getLettuceClientConfiguration( clientResources, this.properties.getLettuce().getPool()); return createLettuceConnectionFactory(clientConfig); } 

LettuceConnectionConfiguration中會創建LettuceConnectionFactory實例,並將其注入為redisConnectionFactory類的實例,
然后在JedisConnectionConfiguration中的類似代碼:

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

也會創建一個JedisConnectionFactory 實例,並將其注入為redisConnectionFactory類的實例。
雙方都有@ConditionalOnMissingBean(RedisConnectionFactory.class)約束,所以當LettuceConnectionConfigurationRedisConnectionFactory類被注入了對應的實例后,JedisConnectionConfiguration對應的代碼就不會再執行了,所以最后RedisConnectionFactory類的實例實際上是LettuceConnectionFactory
只要把@Import中的順序換一下就能改變RedisConnectionFactory類的實例了。

可能有的童鞋會問,“如果把@ConditionalOnMissingBean(RedisConnectionFactory.class)去掉呢?”
這樣的話JedisConnectionConfiguration中的@Bean是否能覆蓋掉之前的那個,實現重復注入呢?抱歉,這樣會報錯(大致意思是RedisConnectionFactory已經有一個對應的bean了,不能再注入第二個)。

這個我們可以做個小測試
新建一個Spring Boot項目,勾一個web即可。
新建BC類。
BC類用來模擬LettuceConnectionConfigurationJedisConnectionConfiguration
這里類上沒有添加@Configuration注解也是為了不被Spring掃描到,然后通過@Import才會進行注入。

public class B{ @Bean @ConditionalOnMissingBean(TestInfoA.class) public TestInfoB testInfoA() { return new TestInfoB(); } } public class C{ @Bean @ConditionalOnMissingBean(TestInfoA.class) public TestInfoC testInfoA() { return new TestInfoC(); } } 

新建
TestInfoATestInfoBTestInfoC。其中TestInfoA為接口,TestInfoBTestInfoC都實現了TestInfoA。用來模擬RedisConnectionFactory接口,JedisConnectionFactoryLettuceConnectionFactory

public interface TestInfoA { } public class TestInfoB implements TestInfoA{ } public class TestInfoC implements TestInfoA{ } 

新建TestInfo,模擬RedisTemplate

public class TestInfo { private TestInfoA info; public TestInfoA getInfo() { return info; } public void setInfo(TestInfoA info) { this.info = info; } } 

新建TestConfig,用來模擬RedisAutoConfiguration

@Configuration @Import({B.class,C.class}) public class TestConfig { @Bean @ConditionalOnMissingBean(name = "testInfo") public TestInfo testInfo(TestInfoA param) { TestInfo info = new TestInfo(); info.setInfo(param); return info; } } 

為了更好的展示,所以這里的結構完全仿照redis-starter的,實際上也不用那么復雜就是了,然后在TestConfig中的testInfo方法中打個斷點,為了看TestInfoA實際上是TestInfoB還是TestInfoC類,運行。
在這里插入圖片描述
可以看到實際上是TestInfoB,而@import中也是B在前。
然后改成@Import({C.class,B.class})
然后結果
在這里插入圖片描述
可以看出是按照出現在@Improt中的順序來注入的。
然后測試下把B,C類的@ConditionalOnMissingBean(TestInfoA.class)注釋掉
報錯

The bean ‘testInfoA’, defined in class path resource
[com/my/startingProcedure/my/C.class], could not be registered. A bean
with that name has already been defined in class path resource
[com/my/startingProcedure/my/B.class] and overriding is disabled.

總結:redisTemplate方法中的RedisConnectionFactory其實是LettuceConnectionFactory
然后我們就可以通過這個注入的RedisTemplate來操作redis了。

3. spring-boot-autoconfigure

Spring Boot可以依據classpath里面的依賴內容來自動配置bean到IOC容器。
但是要開啟這個自動配置功能需要添加@EnableAutoConfiguration注解。

上面指的自動配置功能事實上就是spring-boot-autoconfigure模塊
然后讓我們打開一個Spring Boot項目的啟動項,是否注意到有一個@SpringBootApplication注解,這個是默認就有的。然后點開

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { } 

發現@EnableAutoConfiguration,也就是說Spring Boot是默認開啟自動配置功能的,即spring-boot-autoconfigure模塊是被默認引用的。
然后讓我們看下spring-boot-autoconfigure.jar中的該文件
在這里插入圖片描述
相信能夠找到RedisAutoConfiguration
在這里插入圖片描述
在這里插入圖片描述
EnableAutoConfiguration是不是和剛才講到的注解一模一樣呢?_(:з」∠*)_

這里還涉及到了Spring Boot的啟動過程

public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances( SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; } 

在Spring Boot啟動時,會在refreshContext(context);階段完成配置類的解析、各種BeanFactoryPostProcessor和BeanPostProcessor的注冊、國際化配置的初始化、web內置容器的構造等等,這時會讀取pom中引入jar的配置文件/META-INF/spring.factories,所以這里EnableAutoConfiguration下的所有類都會被實例化並注入Spring容器。
所以RedisAutoConfiguration就被掃描到了。

再來回顧下RedisAutoConfiguration

@Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) public class RedisAutoConfiguration { } 

會發現@ConditionalOnClass(RedisOperations.class),如果想要被掃描到還需要在classpath中存在RedisProperties.class,這個又在哪呢?
點開RedisProperties.class,會發現其存在於spring-data-redis-2.1.3.RELEASE.jar
在這里插入圖片描述
但我們貌似沒有引入spring-data-redis,這個是哪里來的呢?先讓我們先看下之前pom中的引入,

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 

然后ctrl+左鍵繼續查看
在這里插入圖片描述
能看到版本了,再繼續查看。
在這里插入圖片描述
在這里插入圖片描述
發現其會引入spring-data-redis,因此只有當我們在pom中引入spring-boot-starter-data-redis時,RedisAutoConfiguration才會真正的開啟掃描。這也體現了Spring Boot的即插即用和方便快捷的自動配置。
然后下面還有一個io.lettuce,而之前在RedisAutoConfiguration中我們知道redisTemplate方法最終會把一個LettuceConnectionFactory實例注入Spring容器,而在這里實際上就已經大致表明了RedisAutoConfiguration會使用Lettuce客戶端了。

4.總結

當要使用Spring Boot提供的redis客戶端功能時,注入RedisTemplate的流程大致如下。
1.pom中引入spring-boot-starter-data-redis,並配置application.properties
2.pom會根據spring-boot-starter-data-redis來引入spring-data-redis
3.spring-data-redis中包含RedisOperations類。
4.啟動Spring Boot,在refreshContext(context);中會初始化beanFactory,讀取配置信息,初始化Spring容器,注入bean。因為@EnableAutoConfiguration開啟的關系,會讀取配置中EnableAutoConfiguration相關的類,並實例化注入Spring 容器。
5.根據配置文件掃描到RedisAutoConfiguration。當RedisOperations存在時RedisAutoConfiguration才會被掃描。
6.通過@EnableConfigurationProperties(RedisProperties.class)@ConfigurationProperties(prefix = "spring.redis"),把application.properties中的對應屬性進行綁定,並注入RedisProperties配置類。
7.RedisAutoConfiguration中的@Import會引入LettuceConnectionConfigurationJedisConnectionConfiguration
8.LettuceConnectionConfigurationJedisConnectionConfiguration被掃描,掃描到內部的@Bean,使用上一步中注入的RedisProperties bean作為參數來實例化LettuceConnectionFactoryJedisConnectionFactory,並以RedisConnectionFactory類注入Spring容器。
8.掃描並注入RedisAutoConfiguration類內的@Bean,其中會使用RedisConnectionFactory bean作參數實例化RedisTemplate
9.將RedisTemplate實例注入。
10.然后就能通過引用RedisTemplate來操作redis了。


五.創建自定義starter

my-redis-starter項目代碼下載 點我
完成后的項目結構
在這里插入圖片描述

1.新建maven項目

在這里插入圖片描述
結構最簡單的就行
在這里插入圖片描述

2.引入spring-boot-autoconfigure

在pom中引入spring-boot-autoconfigure jar。

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>1.5.4.RELEASE</version> </dependency> </dependencies> 

因為需要用到Spring Boot的autoconfigure功能進行自動化配置。

3.引入相關外部jar

引入jedis-2.9.0.jar,commons-pool2-2.4.2.jar
因為相關的jar已經放在項目下了(/src/WEB-INF/lib),所以直接引入即可。
在這里插入圖片描述

4.新建配置類

新建MyRedisProperties.java,用來綁定配置文件中的屬性值。

@ConfigurationProperties(prefix = "my.redis") public class MyRedisProperties { //Redis服務器IP private String ADDR = "192.168.0.41"; //Redis的端口號 private int PORT = 6379; //訪問密碼 private String AUTH = "admin"; public String getADDR() { return ADDR; } public void setADDR(String aDDR) { ADDR = aDDR; } public int getPORT() { return PORT; } public void setPORT(int pORT) { PORT = pORT; } public String getAUTH() { return AUTH; } public void setAUTH(String aUTH) { AUTH = aUTH; } /** * 初始化Redis連接池 */ public JedisPool getJedisPool(){ JedisPoolConfig config = new JedisPoolConfig(); //省略具體設置 JedisPool myJedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH); return myJedisPool; } } 

這里把一些參數設置省略了,只保留了最重要的url,port,password3個屬性,詳細可下載源碼查看。
當前類會將application.properties中的my.redis.ADDR,my.redis.PORT ,my.redis.AUTH 綁定到對應的屬性中,並且提供了一個創建連接池的方法。

5.新建redis操作模板類

新建JedisTemplete.java

public class JedisTemplete { private JedisPool jedisPool; public JedisPool getJedisPool() { return jedisPool; } public void setJedisPool(JedisPool jedisPool) { this.jedisPool = jedisPool; } /** * 獲取Jedis實例 * @return */ public Jedis getJedis() { try { if (jedisPool != null) { Jedis resource = jedisPool.getResource(); return resource; } else { return null; } } catch (Exception e) { e.printStackTrace(); return null; } } /** * 釋放jedis資源 * @param jedis */ public void close(final Jedis jedis) { if (jedis != null) { jedis.close(); } } public String getValue(String key) { return getJedis().get(key); } } 

使用連接池連接redis服務器,並提供了一個根據key查詢value的方法。

6.新建自動化配置類

新建MyRedisAutoConfiguration.java

@Configuration @ConditionalOnClass(MyRedisProperties.class) @EnableConfigurationProperties(MyRedisProperties.class) public class MyRedisAutoConfiguration { @Bean @ConditionalOnMissingBean(name="jedisTemplete") public JedisTemplete jedisTemplete(MyRedisProperties myRedisProperties) { JedisTemplete jedisTemplete = new JedisTemplete(); jedisTemplete.setJedisPool(myRedisProperties.getJedisPool()); return jedisTemplete; } } 
  • @ConditionalOnClass(MyRedisProperties.class),當存在MyRedisProperties.class時才會進行掃描。
  • @EnableConfigurationProperties(MyRedisProperties.class),進行屬性綁定,當當前類被掃描時,才會去創建MyRedisProperties實例,並綁定application.properties中對應的屬性,然后注入Spring容器。
  • jedisTemplete方法,因為注解@Bean,所以在MyRedisAutoConfiguration 被掃描到時,也會掃描該方法並生成實例注入Spring容器。
    public JedisTemplete jedisTemplete(MyRedisProperties myRedisProperties)
    myRedisProperties參數,就是通過@EnableConfigurationProperties(MyRedisProperties.class)注入的MyRedisProperties類實例。
  • 通過myRedisProperties獲取到JedisPool
  • 創建JedisTemplete 實例,並將連接池賦給它。
  • 返回創建的JedisTemplete 實例,因為注解@Bean,所以會將其注入Spring容器,對應類為JedisTemplete

7.新建spring.factories配置文件

新建src/main/resources/META-INF/spring.factories文件。

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.auto.config.MyRedisAutoConfiguration 

寫入剛才創建的MyRedisAutoConfiguration類全名,注意前半段為EnableAutoConfiguration,這樣在Spring Boot啟動時,才會在配置文件中掃描到MyRedisAutoConfiguration,進而去掃描該類。

8.測試

(1)新建一個Spring Boot項目,在pom中引入剛才創建的maven項目。

<dependency> <groupId>com.my.redis</groupId> <artifactId>my-redis-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> 

(2)創建一個Controller,用來查看jedisTemplete是否被注入,能否連接到redis服務器並獲取到數據。

@RestController @RequestMapping(value="/print") public class PrintController { @Autowired private JedisTemplete jedisTemplete; @ResponseBody @RequestMapping(value="/getRedis") public String getRedis() { return jedisTemplete.getValue("123"); } } 

(3)配置application.properties
添加配置信息

my.redis.ADDR=redis服務器的url
my.redis.PORT=端口
my.redis.AUTH=密碼 

(4)然后讓我們先在redis中存一個值,key:123,value:321。
在這里插入圖片描述
(5)啟動測試
在這里插入圖片描述
成功獲取。

總結:自定義starter時
1.首先需要在pom中引入spring-boot-autoconfigure
2.新建XXXAutoConfiguration,然后引入需要注入的類。
3.配置spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=XXXAutoConfiguration類全路徑
//當有多個時
org.springframework.boot.autoconfigure.EnableAutoConfiguration=/
A,/
B,/
C

轉自:https://blog.csdn.net/yeyinglingfeng/article/details/87790700


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM