springboot自動裝配原理
第一次使用springboot的時候,都感覺很神奇。只要加入一個maven的依賴,寫幾行配置,就能注入redisTemple,rabbitmqTemple等對象。
這一切要從spring的的@bean
和@Configuration
注解說起
如果spring掃描到一個類加了@Configuration注解,那么這個類下面的@bean注解的返回對象就會注冊到spring的容器里面
然后就能通過@Autowired注解獲取bean
以springboot里面的RabbitAutoConfiguration
為例子,他位於boot.autoconfigure包下面。只要spring容器掃描到這個類,就能把類下面的bean對象注冊到容器。
那么現在的問題是,$\color{red}{怎么告訴spring容器@Configuration的類路徑}$
這個就是springboot要做的事。
springboot啟動的時候會掃描所以依賴的jar包下面的META-INF文件夾下面的spring.factories文件。
然后找這個文件的關鍵字org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
,這個關鍵字后面的字符串就是告訴spring要加載哪些@Configuration
的類
所以要寫一個自己的start需要做以下幾件事##
- 創建一個maven工程,寫一個自己的
@Configuration
類 - 在META-INF文件夾下面創建spring.factories文件,配置自己剛剛的Configuration類路徑。
- 打包到倉庫。
- 新建springboot工程引用剛剛的包依賴。
開始
一、創建一個maven工程,寫一個自己的@Configuration
類
我寫了一個自己的EujianRedisTemplate
類,用來操作redis
pom文件如下
<?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.bootstart</groupId>
<artifactId>eujian-spring-boot-starter</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.1.0.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
</project>
寫EujianRedisTemplate類
import org.springframework.cglib.core.internal.Function;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class EujianRedisTemplate {
private JedisPool pool;
public EujianRedisTemplate(JedisPool pool) {
this.pool = pool;
}
public String getString(String key){
String value = redisFun(jedis -> {
return jedis.get(key);
});
return value;
}
public void setString (String key,String object){
redisFun(jedis -> {
jedis.set(key,object);
return null;
});
}
public <T>T redisFun (Function<Jedis,T> function){
Jedis resource = pool.getResource();
T apply = function.apply(resource);
resource.close();
return apply;
}
}
EujianProperties用於讀取配置
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("eujian.redis")
public class EujianProperties {
private String host = "127.0.0.1";
private Integer port = 6379;
private Integer timeout = 2000;
private String password;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
AutoConfig類
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
@EnableConfigurationProperties(EujianProperties.class)
public class AutoConfig {
@Autowired
private EujianProperties eujianProperties;
@Bean
public JedisPool jedisPool (){
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(8);
config.setMaxTotal(18);
JedisPool pool = new JedisPool(config, eujianProperties.getHost(), eujianProperties.getPort(), eujianProperties.getTimeout(), eujianProperties.getPassword());
return pool;
}
@Bean
public EujianRedisTemplate eujianJedis (JedisPool jedisPool){
return new EujianRedisTemplate(jedisPool);
}
}
二、 在META-INF文件夾下面創建spring.factories文件,配置自己剛剛的Configuration類路徑。
在resources下面新建META-INF文件夾,再新建spring.factories文件
文件內容如下
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.bootstart.maven.AutoConfig
三、執行mvn install
打包到本地
四、新建一個boot工程,pom依賴增加dependency如下
<dependency>
<groupId>com.bootstart</groupId>
<artifactId>eujian-spring-boot-starter</artifactId>
<version>1.0</version>
</dependency>
application.properties文件增加配置
eujian.redis.host=39.108.83.105
編寫單元測試類
import com.bootstart.maven.EujianRedisTemplate;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class BootstartApplicationTests {
@Autowired
private EujianRedisTemplate eujianRedisTemplate;
@Test
public void contextLoads() {
eujianRedisTemplate.setString("1","qw");
String string = eujianRedisTemplate.getString("1");
System.out.println(string);
}
}
執行單元測試,EujianRedisTemplate類注入成功
boot項目地址
github: https://github.com/hd-eujian/bootstart.git
碼雲:https://gitee.com/guoeryyj/bootstart.git
maven項目地址
github: https://github.com/hd-eujian/maven-start.git
碼雲: https://gitee.com/guoeryyj/maven-start.git