springboot如何讀取自定義properties并注入到bean中
讀取自定義properties注入到bean
在使用springboot項(xiàng)目時(shí),可使用@value的方式直接讀取application.properties中的文件,但有時(shí)我們需要配置自定義的properties,下面方法將在springboot啟動(dòng)時(shí)利用fileinputstream讀取properties文件中的內(nèi)容,并注入到bean中,@Configuration注解會(huì)在springboot啟動(dòng)時(shí)執(zhí)行一次,代碼如下:
package com.shanqis.parking.properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * 讀取resource下的.properties文件,將文件中的內(nèi)容封裝到map中,注入到bean中方便依賴注入 * * @author Administrator */ @Configuration public class PropertiesClassLoader { private Logger logger = LoggerFactory.getLogger(PropertiesClassLoader.class); private Map<String, Object> versionProperties = new HashMap<>(16); private void init(String name) { try { Properties properties = new Properties(); InputStream in = PropertiesClassLoader.class.getClassLoader().getResourceAsStream(name + ".properties"); properties.load(in); logger.info("加載{}.properties參數(shù)", name); for (String keyName : properties.stringPropertyNames()) { String value = properties.getProperty(keyName); if ("version".equals(name)) { versionProperties.put(keyName, value); } logger.info("{}.properties---------key:{},value:{}", name, keyName, value); } logger.info("{}.properties參數(shù)加載完畢", name); } catch (IOException ignored) { } } @Bean(name = "versionProperties") public Map<String, Object> commonMap() { init("version"); return versionProperties; } }
springboot啟動(dòng)日志如下
然后在controller層或者service層等可以這樣使用
/** * 讀取common.properties文件 */ @Autowired @Qualifier("commonMap") protected Map<String, String> commonMap;
springboot bean實(shí)例化和屬性注入過程
springboot版本(2.0.4 RELEASE)
大致描述springboot中bean的實(shí)例化和屬性注入過程流程
1) 在某一時(shí)刻Spring調(diào)用了Bean工廠的getBean(beanName)方法。beanName可能是simpleController,或者simpleService,simpleDao,順序沒關(guān)系(因?yàn)楹竺鏁?huì)有依賴關(guān)系的處理)。我們假設(shè)simpleController吧
2)getBean方法首先會(huì)調(diào)用Bean工廠中定義的getSingleton(beanName)方法,來判斷是否存在該名字的bean單例,如果存在則返回,方法調(diào)用結(jié)束(spring默認(rèn)是單例,這樣可以提高效率)
3) 否則,Spring會(huì)檢查是否存在父工廠,如果有則返回,方法調(diào)用結(jié)束
4) 否則,Spring會(huì)檢查bean定義(BeanDefinition實(shí)例,用來描述Bean結(jié)果,component-scan掃描后,就是將beanDefinition實(shí)例放入Bean工廠,此時(shí)還沒有被實(shí)例化)是否有依賴關(guān)系,如果有,執(zhí)行1)步,獲取依賴的bean實(shí)例
5) 否則,Spring會(huì)嘗試創(chuàng)建這個(gè)bean實(shí)例,創(chuàng)建實(shí)例前,Spring會(huì)檢查調(diào)用的構(gòu)造器,并實(shí)例化該Bean,(通過Constructor.newInstance(args)進(jìn)行實(shí)例化)
6) 實(shí)例化完成后,Spring會(huì)調(diào)用Bean工廠的populateBean方法來填充bean實(shí)例的屬性,也就是自動(dòng)裝配。populateBean方法便是調(diào)用了BeanPostProcessor實(shí)例來完成屬性元素的自動(dòng)裝配工作
7)在元素裝配過程中,Spring會(huì)檢查被裝配的屬性是否存在自動(dòng)裝配的其他屬性,然后遞歸調(diào)用getBean方法,知道所有@Autowired的元素都被裝配完成。如在裝配simpleController中的simpleService屬性時(shí),發(fā)現(xiàn)SimpleServiceImpl實(shí)例中存在@Autowired屬性simpleDao,然后調(diào)用getBean(simpleDao)方法,同樣會(huì)執(zhí)行1)----7)整個(gè)過程。所有可以看成一個(gè)遞歸過程。
8)裝配完成后,Bean工廠會(huì)將所有的bean實(shí)例都添加到工廠中來。
Bean的實(shí)例化
1. 進(jìn)入SpringApplication類中refreshContext()方法
2. 進(jìn)入AbstractApplicationContext類中refresh()方法,找到this.finishBeanFactoryInitialization()方法,這個(gè)方法就是完成beanFactory的實(shí)例化
3. 進(jìn)入AbstractApplicationContext類中finishBeanFactoryInitialization()方法,找到preInstantiateSingletons()
4. 進(jìn)入DefaultListableBeanFactory類中preInstantiateSingletons()方法,找到getBean()方法
5. 進(jìn)入AbstractBeanFactory類中g(shù)etBean()方法,找到doGetBean()方法
6. 在AbstractBeanFactory類中doGetBean方法中,找到createBean()方法
7. 進(jìn)入AbstractAutowireCapableBeanFactory類中createBean方法中,找到doCreateBean()方法
8. 在AbstractAutowireCapableBeanFactory類中doCreateBean()方法中,找到createBeanInstance()方法,看名字就知道是實(shí)例化bean的
9. 在AbstractAutowireCapableBeanFactory類createBeanInstance()方法中,找到instantiateBean()方法
10. 在AbstractAutowireCapableBeanFactory類instantiateBean()方法中,找到instantiate()方法
11. 在SimpleInstantiationStrategy類instantiate()方法中,找到instantiateClass()方法
12. 在BeanUtils類instantiateClass()方法中,可知bean的實(shí)例化是通過Constructor.newInstance()進(jìn)行實(shí)例化
Bean的屬性注入
1. 在AbstractAutowireCapableBeanFactory類doCreateBean()方法中,找到populateBean()方法,從名字可知是用來填充bean的
2. 在AbstractAutowireCapableBeanFactory類中populateBean()方法,找到postProcessPropertyValues()方法
3. 進(jìn)入AutowiredAnnotationBeanPostProcessor類中postProcessPropertyValues()方法中,找到findAutowiringMetadata()方法,在這個(gè)方法中,如果屬性中含有@Autowired注解則會(huì)遞歸getBean()。沒有然后進(jìn)入inject()方法中
4. 進(jìn)入AutowiredAnnotationBeanPostProcessor類inject方法中,找到resolveDependency()方法,通過這個(gè)方法獲取對(duì)應(yīng)字段的值
5. 進(jìn)入AutowiredAnnotationBeanPostProcessor類inject方法中,找到field.set(bean, value)方法,通過反射將值設(shè)置到屬性中
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring中的@Value讀取配置文件的細(xì)節(jié)處理過程
這篇文章主要介紹了spring中的@Value讀取配置文件的細(xì)節(jié)處理過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09深入學(xué)習(xí)java8?中的CompletableFuture
本文主要介紹了java8中的CompletableFuture,CompletableFuture實(shí)現(xiàn)了CompletionStage接口和Future接口,前者是對(duì)后者的一個(gè)擴(kuò)展,增加了異步回調(diào)、流式處理、多個(gè)Future組合處理的能力,使Java在處理多任務(wù)的協(xié)同工作時(shí)更加順暢便利,下文需要的朋友可以參考一下2022-05-05SpringBoot使用SensitiveWord實(shí)現(xiàn)敏感詞過濾
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何使用SensitiveWord實(shí)現(xiàn)敏感詞過濾功能,文中示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-01-01SpringBoot中@ConfigurationProperties注解實(shí)現(xiàn)配置綁定的三種方法
這篇文章主要介紹了SpringBoot中@ConfigurationProperties注解實(shí)現(xiàn)配置綁定的三種方法,文章內(nèi)容介紹詳細(xì)需要的小伙伴可以參考一下2022-04-04Java 實(shí)現(xiàn)repalceAll只替換第二個(gè)匹配到的字符串
這篇文章主要介紹了Java 實(shí)現(xiàn)repalceAll只替換第二個(gè)匹配到的字符串,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12Java設(shè)計(jì)模式編程中的工廠方法模式和抽象工廠模式
這篇文章主要介紹了Java設(shè)計(jì)模式編程中的工廠方法模式和抽象工廠模式,設(shè)計(jì)模式的建立有利于團(tuán)隊(duì)協(xié)作時(shí)代碼的共同維護(hù),需要的朋友可以參考下2016-01-01