解決springboot自定義配置Boolean屬性不能生效的問題
springboot自定義配置Boolean屬性不能生效
屬性名不能是is開頭,例如isLog屬性,你在配置文件中不管怎么給這個屬性設(shè)值都不會生效,只需改成log即可。
我使用的版本
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.RELEASE</version> <relativePath/> </parent>
springboot自動配置原理
springboot自動配置
1、概述
自動配置的功能是其簡化運(yùn)用的關(guān)鍵技術(shù),思想就是約定大于配置,意思就是一個工程約定必須要有事務(wù)功能,要有aop功能,要有mvc功能等,所以springboot在創(chuàng)建工程的時候自動把這些功能所需的類實例化并加入到spring容器了,這個就是約定大于配置,約定了必須要有這些功能。
2、springboot中的SPI機(jī)制
java原生的SPI,是一種服務(wù)發(fā)現(xiàn)機(jī)制( Service Provider Interface)。
它通過在ClassPath路徑下的META-INF/services文件夾查找文件,自動加載文件里所定義的類。
這一機(jī)制為很多框架擴(kuò)展提供了可能,比如在Dubbo、JDBC中都使用到了SPI。
- 2.1、JDK中的SPI機(jī)制
public interface Log { boolean support(String type); void info(); }
在resources/META-INF/services目錄創(chuàng)建文件,文件名稱必須跟接口的完整限定名相同。
這個接口文件中配置了該接口的所有實現(xiàn)類的完整限定名。
然后jdk api 加載配置文件
//jdk api 加載配置文件配置實例 ServiceLoader<Log> all = ServiceLoader.load(Log.class);
- 2.2、springboot中的SPI機(jī)制
具體流程和上面差不多,在工程的resources下面創(chuàng)建META-INF文件夾,在文件夾下創(chuàng)建spring.factories文件,在文件配置內(nèi)容如下:
com.ss.yc.spi.Log=\ com.ss.yc.spi.Log4j,\ com.ss.yc.spi.Logback,\ com.ss.yc.spi.Slf4j
配置的key就是接口完整限定名,value就是接口的各個實現(xiàn)類,用","號隔開。
loadFactoryNames方法獲取實現(xiàn)了接口的所有類的名稱
@Test public void test() { List<String> strings = SpringFactoriesLoader .loadFactoryNames(Log.class, ClassUtils.getDefaultClassLoader()); for (String string : strings) { System.out.println(string); } }
loadFactories方法獲取實現(xiàn)了接口的所有類的實例
@Test public void test1() { List<String> strings = SpringFactoriesLoader .loadFactories(Log.class, ClassUtils.getDefaultClassLoader()); for (String string : strings) { System.out.println(string); } }
- 2.3、我們以SpringFactoriesLoader.loadFactoryNames(Log.class, ClassUtils.getDefaultClassLoader());方法調(diào)用為例分析其源碼
可以看到springboot spi是加載了整個工程的jar包和自己工程定義的spring.factories文件的。
其核心代碼
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
public static Properties loadProperties(Resource resource) throws IOException { Properties props = new Properties(); //核心代碼,把文件包裝成properties對象 fillProperties(props, resource); return props; }
springboot中的SPI其實就是加載整個工程里面的spring.factories文件,然后把文件里面的內(nèi)容建立一個key和value的映射關(guān)系,只是這個映射關(guān)系是一個類型和list的映射關(guān)系。
3、@EnableAutoConfiguration
@EnableAutoConfiguration注解是springboot自動配置的核心注解,就是因為有這個注解存在就會把例如事務(wù),緩存,aop,mvc等功能自動導(dǎo)入到springboot工程中,Spring框架提供的各種名字為@Enable開頭的Annotation定義,比如@EnableScheduling、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其實一脈相承,簡單概括一下就是,借助@Import的支持,收集和注冊特定場景相關(guān)的bean定義。
@SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... }
@Import了一個類,這個AutoConfigurationImportSelector自動配置類
- 3.1、DeferredImportSelector
DeferredImportSelector該接口是ImportSelector接口的一個子接口,那么它是如何使用的呢?
// public class DeferredImportSelectorDemo implements DeferredImportSelector{ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { System.out.println("=====DeferredImportSelectorDemo.selectImports"); return newString[]{DeferredBean.class.getName()}; } //要返回一個實現(xiàn)了Group接口的類 @Override public Class<?extendsGroup> getImportGroup(){ return DeferredImportSelectorGroupDemo.class; } private static class DeferredImportSelectorGroupDemo implements Group{ List<Entry> list=new ArrayList<>(); //收集需要實例化的類 @Override public void process(AnnotationMetadata metadata,DeferredImportSelector selector){ System.out.println("=====DeferredImportSelectorGroupDemo.process"); String[] strings=selector.selectImports(metadata); for(String string:strings){ list.add(newEntry(metadata,string)); } } //把收集到的類返回給spring容器 @Override public Iterable<Entry> selectImports(){ System.out.println("=====DeferredImportSelectorGroupDemo.selectImports"); return list; } } } //要實例的bean public class DeferredBean{}
該類必須是@Import導(dǎo)入進(jìn)來
@Component //Import雖然是實例化一個類,Import進(jìn)來的類可以實現(xiàn)一些接口@Import({DeferredImportSelectorDemo.class}) public class ImportBean{}
這樣就實現(xiàn)了一個類的實例化。
- 3.2、EnableAutoConfigurationImportSelector
而AutoCon?gurationImportSelector類,這個類就是@EnableAutoCon?guration注解中@Import進(jìn)來的類,可以看到該類正是實現(xiàn)了DeferredImportSelector接口的。
該類其實就是收集spring.factories文件中以@EnableAutoCon?guration類型為key的所有的類,然后把這些類交給spring去實例化,而這些類就是我們說的aop、事務(wù)、緩存、mvc等功能的支持類,這就是自動配置的加載原理。
4、@Configuration
就是JavaConfig形式的Spring Ioc容器的配置類使用的那個@Configuration,SpringBoot社區(qū)推薦使用基于JavaConfig的配置形式,所以,這里的啟動類標(biāo)注了@Configuration之后,本身其實也是一個IoC容器的配置類。
其中@Bean的方法,其返回值將作為一個bean定義注冊到Spring的IoC容器,方法名將默認(rèn)成該bean定義的id。
5、@ComponentScan
其實就是自動掃描并加載符合條件的組件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義加載到IoC容器中。
可以通過basePackages等屬性來細(xì)粒度的定制@ComponentScan自動掃描的范圍,如果不指定,則默認(rèn)Spring框架實現(xiàn)會從聲明@ComponentScan所在類的package進(jìn)行掃描
自定義SpringBoot Starter
1.引入項目的配置依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <version>2.1.4.RELEASE</version> </dependency>
2.創(chuàng)建xxxService類
完成相關(guān)的操作邏輯
DemoService.java @Data public class DemoService{ private String str1; private String str2; }
3.定義xxxProperties類
屬性配置類,完成屬性配置相關(guān)的操作,比如設(shè)置屬性前綴,用于在application.properties中配置
//指定項目在屬性文件中配置的前綴為str,即可以在屬性文件中通過 str.str1=springboot,就可以改變屬性類字段 str1 的值了 @SuppressWarnings("ConfigurationProperties") @ConfigurationProperties(prefix = "str") public class DemoProperties { public static final String DEFAULT_STR1 = "I know, you need me"; public static final String DEFAULT_STR2 = "but I also need you"; private String str1 = DEFAULT_STR1; private String str2 = DEFAULT_STR2; }
4.定義xxxAutoConfiguration類
自動配置類,用于完成Bean創(chuàng)建等工作
// 定義 java 配置類 @Configuration //引入DemoService @ConditionalOnClass({DemoService.class}) // 將 application.properties 的相關(guān)的屬性字段與該類一一對應(yīng),并生成 Bean @EnableConfigurationProperties(DemoProperties.class) public class DemoAutoConfiguration { // 注入屬性類 @Autowired private DemoProperties demoProperties; @Bean // 當(dāng)容器沒有這個 Bean 的時候才創(chuàng)建這個 Bean @ConditionalOnMissingBean(DemoService.class) public DemoService helloworldService() { DemoService demoService= new DemoService(); demoService.setStr1(demoProperties.getStr1()); demoService.setStr2(demoProperties.getStr2()); return demoService; } }
5.在resources下創(chuàng)建目錄META-INF
在 META-INF 目錄下創(chuàng)建 spring.factories
在SpringBoot啟動時會根據(jù)此文件來加載項目的自動化配置類
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.demo.springboot.config.DemoAutoConfiguration
6.其他項目中使用自定義的Starter
<!--引入自定義Starter--> <dependency> <groupId>com.lhf.springboot</groupId> <artifactId>spring-boot-starter-demo</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
7.編寫屬性配置文件
#配置自定義的屬性信息 str.str1=為什么我的眼里常含淚水 str.str2=那是因為我對你愛的深沉
8.寫注解使用
@RestController public class StringController { @Autowired private DemoService demoService; //引入自定義Starter中的DemoService @RequestMapping("/") public String addString(){ return demoService.getStr1()+ demoService.getStr2(); } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
JAVA 截取字符串的三種方法 subString,StringUtils,split實例詳解
這篇文章給大家介紹JAVA 截取字符串的三種方法 subString,StringUtils,split,每種方法結(jié)合實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-12-12MyEclipse8.6首次運(yùn)行maven項目圖標(biāo)上沒有小M的標(biāo)識怎么解決
myeclipse8.6導(dǎo)入maven項目后識別為普通java項目,即項目圖標(biāo)上沒有小M的標(biāo)識。這時是無法直接運(yùn)行的,怎么解決這一問題呢?下面小編給大家?guī)砹私鉀Q方案,需要的朋友參考下吧2016-11-11SpringBoot使用Redis對用戶IP進(jìn)行接口限流的示例詳解
使用接口限流的主要目的在于提高系統(tǒng)的穩(wěn)定性,防止接口被惡意打擊,這篇文章主要介紹了SpringBoot使用Redis對用戶IP進(jìn)行接口限流的示例代碼,需要的朋友可以參考下2023-07-07Docker 解決openjdk容器里無法使用JDK的jmap等命令問題
這篇文章主要介紹了Docker 解決openjdk容器里無法使用JDK的jmap等命令問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12教你快速搭建sona服務(wù)及idea使用sona的方法
Sonar 是一個用于代碼質(zhì)量管理的開放平臺。通過插件機(jī)制,Sonar 可以集成不同的測試工具,代碼分析工具,以及持續(xù)集成工具,本文給大家分享搭建sona服務(wù)及idea使用sona的方法,感興趣的朋友一起看看吧2021-06-06