前兩天,一位朋友面試時又被問到了starter。當我在幫他做模擬面試時,我刻意強調了一下,一定要自己去動手寫一個 自訂starter,果然面試中被問到了。
可能部分人沒有經歷過從Servlet到Spring MVC,如果經歷過就知道那組態是相當的繁瑣,於是後面除了個Spring Boot。
學過Spring Boot的朋友應該知道,有句話用來形容Spring Boot:約定大於設定。
為什麼說Spring Boot會被稱為約定大於配置呢?
Spring Boot被稱為"約定大於配置"的原因是因為它採用了約定優於配置的設計理念。傳統的Java開發需要進行大量的配置,如XML檔案、註解等,這些配置需要開發人員自行指定。而Spring Boot則透過提供一些預設設定和約定來簡化開發流程,減少了開發人員需要手動設定的工作量。
Spring Boot透過一些預設的設定屬性和約定來自動完成一些常見的設定工作,如自動設定資料來源、自動設定Web伺服器、自動設定日誌等。開發人員只需按照約定的方式組織程式碼和設定文件,即可快速建立一個可運行的應用程式。
這種約定大於配置的設計概念使得開發人員不再需要專注於一些常規的配置細節,更專注於業務邏輯的實現。同時,Spring Boot也提供了一些可擴展的配置選項,使得開發人員可以根據自己的需求進行客製化和擴展。
總的來說,Spring Boot的約定大於配置的設計理念使得開發人員能夠更加快速、高效地開發應用程序,並且減少了配置的複雜性。這也是Spring Boot能夠成為Java開發中廣泛使用的框架之一的原因。
在面試中,問你說一下Spring Boot自動組裝原理,咱們可以簡單的這麼來回答:
Spring Boot的自動裝配原理是透過
@EnableAutoConfiguration
註解和spring.factories
檔案來實現的。
@EnableAutoConfiguration
註解是用來開啟自動組裝的功能,該註解通常放在應用的主類別上。
spring.factories
檔案是一個位於META-INF目錄下的設定文件,其中定義了各個自動組裝類別的全限定名稱。當Spring Boot啟動時,會載入classpath下的所有
spring.factories
文件,並根據其中定義的自動組裝類別的全限定名,將其實例化並新增至Spring應用上下文中。自動組裝類別通常會透過
@Configuration
註解來標註,同時會使用各種註解(如@ComponentScan
、@Import
等)來實現對應的自動裝配邏輯。透過
@EnableAutoConfiguration
註解和spring.factories
文件,Spring Boot可以根據應用的依賴和設定訊息,自動載入和配置相應的元件,簡化了應用的配置和開發過程。
背一遍或許兩天就忘了,再背一遍也許能記得個大概。
其實,我們只要清楚如何自訂一個starter,再去回答上面的問題會輕鬆很多。
我們在使用Spring Boot開發時,最常見的就是各種starter。
Spring Boot常用的starter有很多,以下是一些常見的starter:
這些starter可以根據應用程式的需求選擇使用,它們提供了各種功能和便利,簡化了應用程式的開發和配置過程。
從命名上大家會發現都是以spring-boot-starter
開頭的spring-boot-starter-xxx
。
但,我們在專案中也簡單過這樣的:mybatis-spring-boot-starter
,並不是上面的那種命名方式。
其實,我們通常稱以spring-boot-starter開頭的spring-boot-starter-xxx
是spring官方給咱們搞的,xxx-spring-boot-starter
這種格式就是自己搞的,只是個命名而已。
我們為何不能自己也來搞個starter過過癮唄,哈哈哈,開搞。
我們來搞一個redisson的starter。
第一步建立一個Spring Boot項目,命名為:redisson-spring-boot-starter
。
其中,pom依賴重點:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.3.1.RELEASE</version> <!-- 不让jar进行传递 避免jar包冲突--> <optional>true</optional> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.13.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies>
建立配置解析類別:RedissonProperties
/** * @author tianwc 公众号:java后端技术全栈、面试专栏 * @version 1.0.0 * @date 2023年07月20日 11:35 * 在线刷题 1200+题和1000+篇干货文章:<a href="http://woaijava.cc/">博客地址</a> * * 解析配置项 */ @ConfigurationProperties(prefix = "tian.redisson") public class RedissonProperties { private String host="localhost"; private int port=6379; private int timeout; //get set 省略 }
自動組裝類別:RedissonAutoConfiguration
/** * @author tianwc 公众号:java后端技术全栈、面试专栏 * @version 1.0.0 * @date 2023年07月20日 11:27 * 在线刷题 1200+题和1000+篇干货文章:<a href="http://woaijava.cc/">博客地址</a> */ //(条件装配)只有在我们的classpath目录下有Redisson.class 我们才自动装配RedissonClient bean //@ConditionalOnClass(Redisson.class) @EnableConfigurationProperties(RedissonProperties.class) @Configuration public class RedissonAutoConfiguration { private static final String PREFIX="redis://"; @Bean public RedissonClient redissonClient(RedissonProperties redissonProperties){ Config config=new Config(); //redis单机模式 config.useSingleServer().setAddress(PREFIX+redissonProperties.getHost()+":"+redissonProperties.getPort()) .setConnectTimeout(redissonProperties.getTimeout()); return Redisson.create(config); } }
然後,在resources目錄下創建:META-INF目錄,在這個目錄下創建spring.factories
文件,文件內容:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.tian.RedissonAutoConfiguration
完事,這麼就搞定了。是不是還沒緩過神來?
再建立個spring Boot項目,把我們自訂的starter引入進來。
<dependency> <groupId>com.tian</groupId> <artifactId>charge-sms-spring-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
因為我們在RedissonProperties
類別中對host和port賦了預設值,所以我們在application.properties檔案中,不配任何參數時就是用到的是預設值。
如果設定的話,如下:
tian.redisson.host=localhost tian.redisson.port=6379 tian.redisson.timeout=1000
但是,你真的在這樣玩的時候,會發現我們平常要配置個什麼的時候,基本上都會提示的,例如:
這樣提示可不就爽了嗎?
要想有这个提示,还得在redisson-spring-boot-starter
中搞点事情。
相关jar上面都已经引入了这里不再赘述。
同样是在META-INF下面创建一个文件(文件名需要注意不要写错):additional-spring-configuration-metadata.json
内容如下:
{ "properties": [ { "name": "tian.redisson.host", "type": "java.lang.String", "description": "redis服务地址ip", "defaultValue": "localhost" }, { "name": "tian.redisson.port", "type": "java.lang.Integer", "description": "redis服务端口号", "defaultValue": 6379 }, { "name": "tian.redisson.timeout", "type": "java.lang.Integer", "description": "redis连接超时时间", "defaultValue": 1000 } ] }
properties
对应一个数组,每个配置项占一个。
name
:就是我们的配置项type
:配置项类型description
:配置项的描述defaultValue
:默认值
重新打包,在使用的项目里执行Reload All Maven。
接着,再去properties文件里配置,就会有对应的提示了。
我们写一个controller来使用:
@Slf4j @RestController @RequestMapping("/test") public class TestController { @Resource private RedissonClient redissonClient; @GetMapping("/redisson") public String redisson() { RBucket bucket = redissonClient.getBucket("name"); if(bucket.get()==null){ bucket.set("公众号:java后端技术全栈"); } return bucket.get().toString(); } }
执行结果:
到这里,我们就搞定了一个自定义starter。
在实际项目中,在自定义starter时,可能还会用到下面这些注解,请注意收藏:
@Conditional
:依照一定的條件進行判斷,滿足條件給容器註冊bean
@ConditionalOnMissingBean
:給定的在bean不存在時,則實例化目前Bean
@ConditionalOnProperty
:設定檔中符合定義的屬性則建立bean,否則不建立
@ConditionalOnBean
:給定的在bean存在時,則實例化目前Bean
@ConditionalOnClass
:當給定的類別名稱在類別路徑上存在,則實例化目前Bean
#@ConditionalOnMissingClass
:當給定的類別名稱在類別路徑上不存在,則實例化當前Bean
上面我們只是搞了一個單機版的,其實還可以搞各種版本的主從、哨兵、cluster等,也可以搞成ssl存取方式。
自訂會了,那麼就該如何在實際專案中使用了,咱們不能老是停留在demo裡,得用到專案中才是王道。
我在充電樁專案中,發送簡訊功能中用到了自訂starter,也用到了模板方法模式。
以上是如何自訂一個starter,你學廢了麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!