SpringBoot自動(dòng)配置原理及案例源碼解析
一、什么是SpringBoot自動(dòng)配置
首先介紹一下什么是SpringBoot,SpringBoost是基于Spring框架開發(fā)出來的功能更強(qiáng)大的Java程序開發(fā)框架,其最主要的特點(diǎn)是:能使程序開發(fā)者快速搭建一套開發(fā)環(huán)境。SpringBoot 能將主流的開發(fā)框架(例如SpringMVC,Dubbo,Mybatis,Redis等),做到像Maven導(dǎo)入Jar包一樣的簡(jiǎn)潔快速,做到開箱即用。其中最關(guān)鍵的技術(shù)就是 SpringBoot定制的各種Starter,通Maven引入Starter就能快速搭建開發(fā)環(huán)境。
二、SpringBoot Starter自動(dòng)裝配案例
在以前單獨(dú)使用SpringMVC Web編程框架時(shí),我們需要單獨(dú)配置DispatcherServlet和Tomcat,使用SpringBoot之后,我們只需要引入SpringBoot-Starter-Web就能直接開始編寫Controller等Web相關(guān)的代碼,這就是SpringBoot為們提供的開箱即用的便捷能力,下面就以SpringBoot-Starter-Web 來說明SpringBoot自動(dòng)配置的關(guān)鍵原理
三、SpringBoot自動(dòng)裝配案例源碼解析
3.1 DispatcherServlet的自動(dòng)配置原理
首先我們定位到SpringBoot自動(dòng)配置的Maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring-boot.version}</version>
</dependency>在依賴的Jar包中我們可以在META-INF/spring.factories中找到自動(dòng)配置類:
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.DispatcherServletConfiguration
下圖是這個(gè)配置類的主要源碼和解析:

下面將上圖中關(guān)鍵的注解功能,分別進(jìn)行功能說明
3.1.1:@EnableConfigurationProperties ({WebMvcProperties.class}) 注解解析
這個(gè)注解表示使WebMvcProperties.class類上的@ConfigurationProperties這個(gè)注解生效,同時(shí)@ConfigurationProperties這個(gè)注解是將application.xml中以 spring.mvc開頭的配置參數(shù)自動(dòng)注入到WebMvcProperties.class類的字段中
3.1.2:@Conditional ({DefaultDispatcherServletCondition.class} 注解解析
該注解的原理就是將滿足特定條件情況下的Bean自動(dòng)加載到Spring容器中,該注解對(duì)應(yīng)的Spring接口就是 rg.springframework.context.annotation.Condition這個(gè)接口
public interface Condition {
boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}3.1.3:@ConditionOnClass注解解析
@ConditionOnClass這個(gè)注解是在當(dāng)程序代碼環(huán)境classpath下存在xxx.class的情況下條件成立,同時(shí)最終也會(huì)調(diào)用到matches方法中,其中關(guān)鍵的源碼如下:
protected static Class<?> resolve(String className, ClassLoader classLoader) throws ClassNotFoundException {
return classLoader != null ? Class.forName(className, false, classLoader) : Class.forName(className);
}從上面可以看到,代碼利用Class.forName方法加載classpath下的xxx.class類,如果加載成功條件就會(huì)成立。最后,在滿足了所有@ConditionOnal注解條件后,SpringBoot就會(huì)自動(dòng)為我們?cè)赟pring容器中注入DispatcherServlet了,無需單獨(dú)配置了,直接引入pring-boot-starter-webr即可開始使用web相關(guān)功能。
3.1.4:小結(jié)
我們以DispatcherServlet是如何自動(dòng)配置到容器中為例,探究了SpringBoot Starter的自動(dòng)配置原理,其中涉及了幾個(gè)關(guān)鍵的注解和步驟:
第一步:涉及到了配置文件的讀取和個(gè)性化配置,這里就涉及到了下面這兩個(gè)注解
@ConfigurationProperties @EnableConfigurationProperties
第二步:設(shè)計(jì)到了在什么條件下才自動(dòng)配置的注解
@Conditional @ConditionalOnClass
第三步:約定了自動(dòng)配置類的加載路徑
/META-INF/spring-factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=自動(dòng)配置類全路徑名稱
在我們了解到了SpringBoot自動(dòng)配置的原理之后,我們就可以自定義一個(gè)SpringBoot Starter來快速搭建我們的開發(fā)環(huán)境了。
四、自定義一個(gè)打印輸入輸出日志的Starter
4.1 首先定義一個(gè)標(biāo)記需要打印出入?yún)⑷罩镜淖⒔釦PrintLog
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PrintLog {
}4.2 定義一個(gè)存放打印日志配置的實(shí)體類
//自動(dòng)注入application配置文件中已log.switch開頭的配置參數(shù)
@ConfigurationProperties("log.switch")
public class LogProperties {
//是否啟用打印日志功能
private Boolean enabled = false;
//是否打印調(diào)用者ip
private Boolean printIp = false;
//是否打印調(diào)用者url
private Boolean printUrl = false
}4.3 定義一個(gè)@PrintLog注解的切面類
@Aspect
public class LogAspect {
private static final Log LOGGER = LogFactory.getLog(LogAspect.class);
private LogProperties logProperties;
@Pointcut("@annotation(com.zl.annotation.PrintLog)")
public void Log(){}
@Around("Log()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
//打印調(diào)用url
if (Boolean.TRUE.equals(logProperties.getPrintUrl())){
LOGGER.info("URL:" + request.getRequestURL().toString());
}
//打印ip
if (Boolean.TRUE.equals(logProperties.getPrintIp())) {
LOGGER.info("IP :" + request.getRemoteAddr());
}
//打印方法
LOGGER.info("method :" + methodName);
//打印參數(shù)
LOGGER.info("parameter :" + Arrays.toString(joinPoint.getArgs()));
Object result = joinPoint.proceed();
//打印返回結(jié)果
LOGGER.info("return :" + JSON.toJSONString(result));
return result;
}
}4.4 定義一個(gè)打印日志的自動(dòng)配置類
@Configuration
@EnableConfigurationProperties({LogProperties.class})
//表示在application配置文件中必須配置log.switch.enabled = true才啟動(dòng)自動(dòng)配置
@ConditionalOnProperty(prefix = "log.switch", value = "enabled", havingValue = "true")
public class LogAutoConfigure {
@Bean
//Advice.class是aop切面中關(guān)鍵的切面方法類(@Before,@After等)
//程序中有Advice.class類說明需要使用切面功能,這時(shí)才加載自定義的切面類
@ConditionalOnClass(Advice.class)
public LogAspect webLogAspect(LogProperties logProperties){
return new LogAspect(logProperties);
}
}總結(jié)
SpringBoot自動(dòng)配置功能帶給我們的是開箱即用,快速便捷的功能,自動(dòng)配置為我們研發(fā)人員帶來的優(yōu)點(diǎn),我主要總結(jié)為以下兩點(diǎn):
- 提高研發(fā)效率 。我們可以快速構(gòu)建開發(fā)環(huán)境,對(duì)于開發(fā)中使用到的開源組件和中間件,我們直接引入對(duì)應(yīng)的Starter就可以直接開發(fā)了,例如Redis和Mybati等,可以直接引入對(duì)應(yīng)的spring-boot-starter-data-redis就可以直接使用RedisTemplate來操作 Redis了,這樣可以極大的提高研發(fā)的效率,無需再進(jìn)行復(fù)雜的起步配置了和各種版本依賴管理了。
- 標(biāo)準(zhǔn)模塊復(fù)用。對(duì)于業(yè)務(wù)開發(fā)中的一些標(biāo)準(zhǔn)模塊,例如常用的一些三方服務(wù),我們可以利用Starter直接配置好,在需要使用的項(xiàng)目中直接引入這個(gè)starter就可以立即使用了,無需再去引入Jar包和編寫配置文件等,同樣的,對(duì)于一些標(biāo)準(zhǔn)非業(yè)務(wù)強(qiáng)耦合的功能,例如監(jiān)控,鑒權(quán)等,也可以定義一個(gè)Starter,需要使用鑒權(quán)和監(jiān)控功能的項(xiàng)目就可以直接復(fù)用了,無需再次開發(fā)。
以上就是SpringBoot自動(dòng)配置原理及案例源碼解析的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot自動(dòng)配置的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java基于QuartzJobBean實(shí)現(xiàn)定時(shí)功能的示例代碼
QuartzJobBean是Quartz框架中的一個(gè)抽象類,用于定義和實(shí)現(xiàn)可由Quartz調(diào)度的作業(yè),本文主要介紹了java基于QuartzJobBean實(shí)現(xiàn)定時(shí)功能的示例代碼,具有一定的參考價(jià)值,感興趣可以了解一下2023-09-09
java 鍵盤輸入一個(gè)數(shù),輸出數(shù)組中指定元素的示例
今天小編就為大家分享一篇java 鍵盤輸入一個(gè)數(shù),輸出數(shù)組中指定元素的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-07-07
深入淺析drools中Fact的equality?modes
這篇文章主要介紹了drools中Fact的equality?modes的相關(guān)知識(shí),本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05

