springboot面試殺手锏-自動配置原理
前言
隨著互聯(lián)網(wǎng)越來越流行,springboot已經(jīng)成為我們無論是工作,還是面試當(dāng)中,不得不掌握的技術(shù)。說起springboot筆者認(rèn)為最重要的功能非自動配置莫屬了,為什么這么說?如果參與過以前spring復(fù)雜項(xiàng)目的朋友肯定,有過這樣的經(jīng)歷,每次需要一個(gè)新功能,比如事務(wù)、AOP等,需要大量的配置,需要導(dǎo)出找jar包,時(shí)不時(shí)會出現(xiàn)jar兼容性問題,可以說苦不堪言。
springboot的出現(xiàn)得益于“習(xí)慣優(yōu)于配置”的理念,沒有繁瑣的配置、難以集成的內(nèi)容(大多數(shù)流行第三方技術(shù)都被集成),這是基于Spring 4.x以上的版本提供的按條件配置Bean的能力。有了springboot的自動配置的功能,我們可以快速的開始一個(gè)項(xiàng)目。
一 什么是自動配置
不知道朋友們在工作當(dāng)中有沒有這樣的經(jīng)歷:
1.1 引入redisTemplate
只要我們在pom.xml文件中引入spring-boot-starter-data-redis-xxx.jar包,然后只要在配置文件中配置redis連接,如:
spring.redis.database = 0spring.redis.timeout = 10000spring.redis.host = 10.72.16.9spring.redis.port = 6379spring.redis.pattern = 1
就可以在service方法中直接注入StringRedisTemplate對象的實(shí)例,可以直接使用了。朋友們有沒有想過這是為什么?
@Autowiredprivate StringRedisTemplate stringRedisTemplate;
1.2 引入transactionTemplate
在項(xiàng)目中只要引入spring-boot-starter-xxx.jar,事務(wù)就自動生效了,并且可以直接在service方法中直接注入TransactionTemplate,用它開發(fā)編程式事務(wù)代碼。是不是很神奇?這又是為什么?
1.3 使用@ConfigurationProperties
使用@ConfigurationProperties可以把指定路徑下的屬性,直接注入到實(shí)體對象中,看看下面這個(gè)例子:
@Data@Component@ConfigurationProperties("jump.threadpool")public class ThreadPoolProperties {private int corePoolSize;private int maxPoolSize;private int keepAliveSeconds;private int queueCapacity;}
只要application.properties這樣配置,就可以自動注入到上面的實(shí)體中
jump.threadpool.corePoolSize=8jump.threadpool.maxPoolSize=16jump.threadpool.keepAliveSeconds=10jump.threadpool.queueCapacity=100
沒錯(cuò),這三個(gè)例子都是springboot自動配置在起作用,我們分為兩種情況:bean的自動配置 和 屬性的自動配置。
二 工作原理
2.1 bean的自動配置
Spring Boot的啟動類上有一個(gè)@SpringBootApplication注解,這個(gè)注解是Spring Boot項(xiàng)目必不可少的注解。
我們先看看@SpringBootApplication注解

它上面定義了另外一個(gè)注解:@EnableAutoConfiguration

該注解的關(guān)鍵功能由@Import提供,其導(dǎo)入的AutoConfigurationImportSelector的selectImports()方法通過SpringFactoriesLoader.loadFactoryNames()掃描所有具有META-INF/spring.factories的jar包下面key是EnableAutoConfiguration全名的,所有自動配置類。
我們看看springboot的spring-boot-autoconfigure-xxx.jar

該jar包里面就有META-INF/spring.factories文件。

這個(gè)spring.factories文件是一組一組的key=value的形式,其中一個(gè)key是EnableAutoConfiguration類的全類名,而它的value是一個(gè)xxxxAutoConfiguration的類名的列表,這些類名以逗號分隔。
@EnableAutoConfiguration注解通過@SpringBootApplication被間接的標(biāo)記在了Spring Boot的啟動類上。在SpringApplication.run(...)的內(nèi)部就會執(zhí)行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應(yīng)的class,然后將所有自動配置類加載到Spring容器中。
SpringApplication.run(...)方法怎么調(diào)到selectImports()方法的
加載過程大概是這樣的:
SpringApplication.run(...)方法 》
AbstractApplicationContext.refresh()方法 》
invokeBeanFactoryPostProcessors(...)方法 》
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(...) 方法 》
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(..)方法 》
AutoConfigurationImportSelector.selectImports
該方法會找到自動配置的類,并給打了@Bean注解的方法創(chuàng)建對象。
postProcessBeanDefinitionRegistry方法是最核心的方法,它負(fù)責(zé)解析@Configuration、@Import、@ImportSource、@Component、@ComponentScan、@Bean等,完成bean的自動配置功能。
回到剛剛第二個(gè)例子TransactionTemplate為什么可以直接引用?
是因?yàn)樵趕pring-boot-autoconfigure-xxx.jar的spring.factories配置文件中,EnableAutoConfiguration全類名下配置了TransactionAutoConfiguration全類名,springboot在啟動的時(shí)候會加載這個(gè)類。

而TransactionAutoConfiguration類是一個(gè)配置類,它里面創(chuàng)建TransactionTemplate類的實(shí)例。

這樣在其他地方就可以直接注入TransactionTemplate類的實(shí)例。
2.2 屬性的自動配置
屬性的自動配置是通過ConfigurationPropertiesBindingPostProcessor類的postProcessBeforeInitialization方法完成,
public Object postProcessBeforeInitialization(Object bean, String beanName)throws BeansException {ConfigurationProperties annotation = getAnnotation(bean, beanName,ConfigurationProperties.class);if (annotation != null) {bind(bean, beanName, annotation);}return bean;}
它會解析@ConfigurationProperties注解上的屬性,將配置文件中對應(yīng)key的值綁定到屬性上。
三 自動配置的生效條件
每個(gè)xxxxAutoConfiguration類上都可以定義一些生效條件,這些條件基本都是從@Conditional派生出來的。
常用的條件如下:
:當(dāng)容器里有指定的bean時(shí)生效:當(dāng)容器里不存在指定bean時(shí)生效:當(dāng)類路徑下有指定類時(shí)生效:當(dāng)類路徑下不存在指定類時(shí)生效:指定的屬性是否有指定的值,比如(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),代表當(dāng)xxx.xxx為enable時(shí)條件的布爾值為true,如果沒有設(shè)置的情況下也為true。
舉個(gè)比較常用的例子看看TransactionAutoConfiguration,是如何使用條件的

總結(jié)
本篇文章從什么是自動配置,工作原理 和 自動配置的生效條件 三個(gè)方面介紹了自動配置的相關(guān)知識點(diǎn)。自動配置又分為:bean的自動配置 和 屬性的自動配置,二者的實(shí)現(xiàn)原理不一樣。自動配置的生效條件用得非常多,建議朋友們好好研究一下。至于如何自定義自動配置類,本篇沒有講,是因?yàn)槲以诹硗庖黄恼?span style="color: rgb(63, 63, 63);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0.578px;text-align: left;">《老司機(jī)手把手教你編寫自己的springboot starter》中仔細(xì)介紹過的,有需要的朋友可以自行查閱。
— 【 THE END 】— 本公眾號全部博文已整理成一個(gè)目錄,請?jiān)诠娞柪锘貜?fù)「m」獲??! 最近面試BAT,整理一份面試資料《Java面試BATJ通關(guān)手冊》,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。
獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) PDF 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。
文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。
謝謝支持喲 (*^__^*)
