日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

springboot-自动配置原理

發(fā)布時(shí)間:2025/3/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot-自动配置原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

一、@SpringBootApplication

二、@EnableAutoConfiguration

1.AutoConfigurationPackages.Registrar.class?批量注冊(cè)組件

2.AutoConfigurationImportSelector.class

三、按需開(kāi)啟自動(dòng)配置

1.得益于按條件裝配@Conditional

2.例如AOP:

四、總結(jié)

五、springboot快速配置


一、@SpringBootApplication

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration // 就是@Configuration。代表當(dāng)前是一個(gè)配置類(lèi) @EnableAutoConfiguration // 開(kāi)啟自動(dòng)配置 // 指定掃描哪些,Spring注解 @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication {

二、@EnableAutoConfiguration

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage // @Import(AutoConfigurationImportSelector.class) // 給容器中導(dǎo)入一個(gè)組件 public @interface EnableAutoConfiguration {

1.AutoConfigurationPackages.Registrar.class?批量注冊(cè)組件

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) //給容器中導(dǎo)入一個(gè)組件 public @interface AutoConfigurationPackage { static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {// 注冊(cè)注解包名下面所有的組件register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));}@Overridepublic Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImports(metadata));}}

2.AutoConfigurationImportSelector.class

(1)、利用getAutoConfigurationEntry(annotationMetadata);給容器中批量導(dǎo)入一些組件

(2)、調(diào)用List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)獲取到所有需要導(dǎo)入到容器中的配置類(lèi)

(3)、利用工廠加載 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader);得到所有的組件

(4)、從META-INF/spring.factories位置來(lái)加載一個(gè)文件。

????默認(rèn)掃描我們當(dāng)前系統(tǒng)里面所有META-INF/spring.factories位置的文件

?? ?文件里面寫(xiě)死了spring-boot一啟動(dòng)就要給容器中加載的所有配置類(lèi)

????spring-boot-autoconfigure-2.3.4.RELEASE.jar包里面也有META-INF/spring.factories

????

雖然我們127個(gè)場(chǎng)景的所有自動(dòng)配置啟動(dòng)的時(shí)候默認(rèn)全部加載。xxxxAutoConfiguration

按照條件裝配規(guī)則(@Conditional),最終會(huì)按需配置。

// org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);configurations = removeDuplicates(configurations);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions); }

三、按需開(kāi)啟自動(dòng)配置

1.得益于按條件裝配@Conditional

可修飾在類(lèi)、方法上。 @ConditionalOnBean // 當(dāng)容器中存在指定的組件時(shí)才。。。 @ConditionalOnMissingBean // 當(dāng)容器中不存在指定的組件時(shí)才。。。 @ConditionalOnClass // 當(dāng)容器中有某一個(gè)類(lèi)時(shí)才。。。 @ConditionalOnMissingClass // 當(dāng)容器中沒(méi)有某一個(gè)類(lèi)時(shí)才。。。 @ConditionalOnResource // 當(dāng)項(xiàng)目類(lèi)路徑存在某個(gè)資源時(shí)才。。。 @ConditionalOnJava // 當(dāng)項(xiàng)目環(huán)境是指定的java版本號(hào)時(shí)才。。。 @ConditionalOnWebApplication // 當(dāng)應(yīng)用是一個(gè)web應(yīng)用時(shí)才。。。 @ConditionalOnSingleCandidate // 當(dāng)容器中只有一個(gè)實(shí)例或者有用@Primary修飾的默認(rèn)bean。 @ConditionalOnProperty // 當(dāng)配置文件中配置了某個(gè)屬性時(shí)才。。。@ConditionalOnBean(name = "tom") @ConditionalOnMissingBean(name = "tom")

?

2.例如AOP:

假如說(shuō)配置文件沒(méi)有spring.aop.auto=true,matchIfMissing默認(rèn)就是true,默認(rèn)就是開(kāi)啟AOP。

我們可以看到里面有大量使用@Conditional判斷。

package org.springframework.boot.autoconfigure.aop;import org.aspectj.weaver.Advice; import org.springframework.aop.config.AopConfigUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy;/** * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration * Auto-configuration} for Spring's AOP support. Equivalent to enabling * {@link EnableAspectJAutoProxy @EnableAspectJAutoProxy} in your configuration. * <p> * The configuration will not be activated if {@literal spring.aop.auto=false}. The * {@literal proxyTargetClass} attribute will be {@literal true}, by default, but can be * overridden by specifying {@literal spring.aop.proxy-target-class=false}. * * @author Dave Syer * @author Josh Long * @since 1.0.0 * @see EnableAspectJAutoProxy */ @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true) public class AopAutoConfiguration {@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Advice.class)static class AspectJAutoProxyingConfiguration {@Configuration(proxyBeanMethods = false)@EnableAspectJAutoProxy(proxyTargetClass = false)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",matchIfMissing = false)static class JdkDynamicAutoProxyConfiguration {}@Configuration(proxyBeanMethods = false)@EnableAspectJAutoProxy(proxyTargetClass = true)@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)static class CglibAutoProxyConfiguration {}}@Configuration(proxyBeanMethods = false)@ConditionalOnMissingClass("org.aspectj.weaver.Advice")@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",matchIfMissing = true)static class ClassProxyingConfiguration {ClassProxyingConfiguration(BeanFactory beanFactory) {if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}}} } @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration {/** The bean name for a DispatcherServlet that will be mapped to the root URL "/"*/public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet";/** The bean name for a ServletRegistrationBean for the DispatcherServlet "/"*/public static final String DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME = "dispatcherServletRegistration";@Configuration(proxyBeanMethods = false)@Conditional(DefaultDispatcherServletCondition.class)@ConditionalOnClass(ServletRegistration.class)@EnableConfigurationProperties(WebMvcProperties.class)protected static class DispatcherServletConfiguration {@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {DispatcherServlet dispatcherServlet = new DispatcherServlet();dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());return dispatcherServlet;}//給容器中加入了文件上傳解析器@Bean@ConditionalOnBean(MultipartResolver.class)//容器中有這個(gè)類(lèi)型組件@ConditionalOnMissingBean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)//容器中沒(méi)有這個(gè)名字 multipartResolver 的組件public MultipartResolver multipartResolver(MultipartResolver resolver) {//給@Bean標(biāo)注的方法傳入了對(duì)象參數(shù),這個(gè)參數(shù)的值就會(huì)從容器中找。//SpringMVC multipartResolver。防止有些用戶(hù)配置的文件上傳解析器不符合規(guī)范// Detect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;}}@Configuration(proxyBeanMethods = false)@Conditional(DispatcherServletRegistrationCondition.class)@ConditionalOnClass(ServletRegistration.class)@EnableConfigurationProperties(WebMvcProperties.class)@Import(DispatcherServletConfiguration.class)protected static class DispatcherServletRegistrationConfiguration {@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,webMvcProperties.getServlet().getPath());registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());multipartConfig.ifAvailable(registration::setMultipartConfig);return registration;}} @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration {private final Encoding properties;public HttpEncodingAutoConfiguration(ServerProperties properties) {this.properties = properties.getServlet().getEncoding();}@Bean@ConditionalOnMissingBeanpublic CharacterEncodingFilter characterEncodingFilter() {CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();filter.setEncoding(this.properties.getCharset().name());filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));return filter;}@Beanpublic LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {return new LocaleCharsetMappingsCustomizer(this.properties);}static class LocaleCharsetMappingsCustomizerimplements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {private final Encoding properties;LocaleCharsetMappingsCustomizer(Encoding properties) {this.properties = properties;}@Overridepublic void customize(ConfigurableServletWebServerFactory factory) {if (this.properties.getMapping() != null) {factory.setLocaleCharsetMappings(this.properties.getMapping());}}@Overridepublic int getOrder() {return 0;}}}

四、總結(jié)

* SpringBoot先加載所有的自動(dòng)配置類(lèi) xxxxxAutoConfiguration

* 每個(gè)自動(dòng)配置類(lèi)按照條件進(jìn)行生效(@Conditionalxxxx),默認(rèn)都會(huì)綁定配置文件指定的值。xxxxProperties里面拿。xxxProperties和配置文件進(jìn)行了綁定

* 生效的配置類(lèi)就會(huì)給容器中裝配很多組件

* 只要容器中有這些組件,相當(dāng)于這些功能就有了

* SpringBoot默認(rèn)會(huì)在底層配好所有的組件。但是如果用戶(hù)自己配置了以用戶(hù)的優(yōu)先(@ConditionalOnMissingBean)

*定制化配置:① 用戶(hù)直接自己@Bean替換底層的組件② 用戶(hù)去看這個(gè)組件是獲取的配置文件什么值就去修改。

xxxxxAutoConfiguration ---> 組件 ---> xxxxProperties里面拿值 ----> application.properties

五、springboot快速配置

1.引入場(chǎng)景依賴(lài)

https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter

2.查看自動(dòng)配置了哪些(選做)

自己分析,引入場(chǎng)景對(duì)應(yīng)的自動(dòng)配置一般都生效了

配置文件中debug=true開(kāi)啟自動(dòng)配置報(bào)告。Negative(不生效)\Positive(生效)

3.修改配置項(xiàng)

(1)參照文檔修改配置項(xiàng)

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html#common-application-properties

(2)自己分析。xxxxProperties綁定了配置文件的哪些。

4.自定義加入或者替換組件

@Bean、@Component。。。

5.自定義器 XXXXXCustomizer

總結(jié)

以上是生活随笔為你收集整理的springboot-自动配置原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。