欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入解析SpringBoot自動配置原理

 更新時(shí)間:2023年11月02日 09:29:50   作者:桐花思雨  
這篇文章主要介紹了深入解析SpringBoot自動配置原理,SpringBoot?的一大好處就是:大大簡化了?Spring?和其他框架的整合配置,為了簡化配置文件使開發(fā)者更專注于業(yè)務(wù)編碼,可以使用?SpringBoot?來進(jìn)行?Web?開發(fā),需要的朋友可以參考下

前言

SpringBoot 的一大好處就是:大大簡化了 Spring 和其他框架的整合配置。傳統(tǒng)的 SSM 套裝雖然很大程度地簡化了 Web 開發(fā),但是其的配置文件卻較為繁瑣,為了簡化配置文件使開發(fā)者更專注于業(yè)務(wù)編碼,可以使用 SpringBoot 來進(jìn)行 Web 開發(fā),其精簡的配置和龐大繁茂的生態(tài)圈絕對令人驚嘆

SpringBoot 之所以可以達(dá)到如此精簡的配置,主要原因就是 SpringBoot自動配置

自動配置原理

本文的 SpringBoot 的版本為 2.0.6 RELEASE

SpringBoot 應(yīng)用的啟動類

SpringBoot 應(yīng)用是從啟動類的 main 方法中啟動,加載 SpringBoot 配置類

@SpringBootApplication
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

@SpringBootApplication 注解

由于 SpringBoot 應(yīng)用是從啟動類的 main 方法中啟動的,我們就有必要查看 @SpringBootApplication 注解它做了什么事情

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
	// 省略 ......
}

可以看到 @SpringBootApplication 這個(gè)注解是一個(gè)復(fù)合注解,它有三個(gè)核心注解,下面我們依次查看它們

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan

@SpringBootConfiguration 注解

表明它是一個(gè)配置類

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

@ComponentScan 注解

它負(fù)責(zé)包的掃描,并排除一些特定的類型(不允許注冊進(jìn) Spring 容器)

@ComponentScan(excludeFilters = {
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

@EnableAutoConfiguration 注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
	// 省略 ......
}

可以看到 @EnableAutoConfiguration 注解是個(gè)復(fù)合注解,有兩個(gè)元注解,我們依次查看它們

  • @AutoConfigurationPackage
  • @Import(AutoConfigurationImportSelector.class)

@AutoConfigurationPackage

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

查看 AutoConfigurationPackages.Registrar

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {
		register(registry, new PackageImport(metadata).getPackageName());
	}

	@Override
	public Set<Object> determineImports(AnnotationMetadata metadata) {
		return Collections.singleton(new PackageImport(metadata));
	}
}

它其實(shí)是注冊了一個(gè) bean 的定義,返回了當(dāng)前主啟動類包的同級以及子級的包組件

@Import(AutoConfigurationImportSelector.class)

在 AutoConfigurationImportSelector 類中查看 selectImports() 方法

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
	if (!isEnabled(annotationMetadata)) {
		return NO_IMPORTS;
	}
	
	AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
				.loadMetadata(this.beanClassLoader);
				
	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 = filter(configurations, autoConfigurationMetadata);
	fireAutoConfigurationImportEvents(configurations, exclusions);
	
	return StringUtils.toStringArray(configurations);
}

再查看 getCandidateConfigurations(annotationMetadata, attributes) 方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
			
	List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
	Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
	return configurations;
}

再查看 loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()) 方法

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {

	String factoryClassName = factoryClass.getName();
	return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

loadSpringFactories 方法調(diào)用如下

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {

	MultiValueMap<String, String> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}

	try {
		Enumeration<URL> urls = (classLoader != null ?
					classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
					ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
		
		result = new LinkedMultiValueMap<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			UrlResource resource = new UrlResource(url);
			Properties properties = PropertiesLoaderUtils.loadProperties(resource);
			for (Map.Entry<?, ?> entry : properties.entrySet()) {
				List<String> factoryClassNames = Arrays.asList(
						StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
				result.addAll((String) entry.getKey(), factoryClassNames);
			}
		}
		cache.put(classLoader, result);
		return result;
	}
	catch (IOException ex) {
		throw new IllegalArgumentException("Unable to load factories from location [" +
				FACTORIES_RESOURCE_LOCATION + "]", ex);
	}
}

該方法的作用:掃描類路徑下所有具有 META-INF/spring.factories 的 jar 包,將掃描到的相應(yīng)類組件注冊進(jìn) Spring 容器中,不過這些掃描到的類組件注冊進(jìn) Spring 容器中需要生效也是有條件的,使用條件注解 @Conditional

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

在這里插入圖片描述

META-INF/spring.factories 的部分內(nèi)容如下

......

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\

......

這些自動配置類都是以 AutoConfiguration 結(jié)尾來命名的,它實(shí)際上就是一個(gè) JavaConfig 形式的 Spring 容器配置類

在此我們以 RedisAutoConfiguration 類為例,舉例說明

@Configuration
@ConditionalOnClass(RedisOperations.class)// 當(dāng)給定的類名在類路徑上存在時(shí),則實(shí)例化當(dāng)前 bean
@EnableConfigurationProperties(RedisProperties.class)// 將 RedisProperties 這個(gè)類注冊進(jìn) spring 容器中
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(
			RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	@Bean
	@ConditionalOnMissingBean
	public StringRedisTemplate stringRedisTemplate(
			RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
		StringRedisTemplate template = new StringRedisTemplate();
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}
}

@Conditional 條件注解

  • @ConditionalOnBean:當(dāng)給定的在 bean 存在時(shí),則實(shí)例化當(dāng)前 bean
  • @ConditionalOnExpression:當(dāng)表達(dá)式為 true 的時(shí)候,才會實(shí)例化一個(gè) bean
  • @ConditionalOnMissingBean:當(dāng)給定的在 bean 不存在時(shí),則實(shí)例化當(dāng)前 bean
  • @ConditionalOnMissingClass:當(dāng)給定的類名在類路徑上不存在時(shí),則實(shí)例化當(dāng)前 bean
  • @ConditionalOnNotWebApplication:不是 web 應(yīng)用
  • @ConditionalOnClass:當(dāng)給定的類名在類路徑上存在時(shí),則實(shí)例化當(dāng)前 bean

RedisProperties 類

該類負(fù)責(zé)讀取配置文件中具體配置,如 spring.redis.host 和 spring.redis.port

@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {

	private int database = 0;

	private String url;

	private String host = "localhost";

	private String password;

	private int port = 6379;

	private boolean ssl;

	private Duration timeout;

	private Sentinel sentinel;

	private Cluster cluster;

	private final Jedis jedis = new Jedis();

	private final Lettuce lettuce = new Lettuce();

	......
}	

當(dāng)我們在使用 maven 引入了相關(guān)的 jar 包的時(shí)候,在類路徑下也就具有了 META-INF/spring.factories 這樣的文件,同時(shí)也就滿足了上面的某些條件注解。這時(shí),maven 引入了相關(guān)的 jar 包的類組件也就成功的注冊進(jìn) Spring 容器中了

自動配置總結(jié)

@SpringBootApplication 它有三個(gè)核心注解:@SpringBootConfiguration,@EnableAutoConfiguration(重點(diǎn)關(guān)注),@ComponentScan

@EnableAutoConfiguration:核心作用是掃描類路徑下所有具有 META-INF/spring.factories 的類組件(配置類),這些類組件都是以 AutoConfiguration 結(jié)尾來命名的,他能讀取在配置文件中配置的屬性信息,如 server.port,redis.port 等

然后將上述掃描到的相應(yīng)類組件注冊進(jìn) Spring 容器中;不過這些掃描到的類組件注冊進(jìn) Spring 容器中需要生效也是有條件的,此時(shí)使用了條件注解 @ConditionOnxxx

當(dāng)我們在使用 maven 或 gradle 引入了相關(guān)的 jar 包的時(shí)候,在類路徑下也就具有了 META-INF/spring.factories 這樣的文件;同時(shí)也就滿足了某些 @ConditionOnxxx 的條件注解。這時(shí),maven 或 gradle 引入了相關(guān)的 jar 包的類組件也就成功的注冊進(jìn) Spring 容器中了

到此這篇關(guān)于深入解析SpringBoot自動配置原理的文章就介紹到這了,更多相關(guān)SpringBoot自動配置原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis-Plus查詢中如何排除標(biāo)識字段

    Mybatis-Plus查詢中如何排除標(biāo)識字段

    這篇文章主要介紹了Mybatis-Plus查詢中排除標(biāo)識字段的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 2022年最新java?8?(?jdk1.8u321)安裝圖文教程

    2022年最新java?8?(?jdk1.8u321)安裝圖文教程

    這篇文章主要介紹了2022年最新java?8?(?jdk1.8u321)安裝圖文教程,截止2022年1月,官方出的jdk1.8目前已更新到8u321的版本,本文通過圖文并茂的形式給大家介紹安裝過程,需要的朋友可以參考下
    2022-08-08
  • Java中的可重入鎖ReentrantLock簡析

    Java中的可重入鎖ReentrantLock簡析

    這篇文章主要介紹了Java中的可重入鎖ReentrantLock簡析,可重入是指同一個(gè)線程如果首次獲得了這把鎖,那么因?yàn)樗沁@把鎖的擁有者,因此有權(quán)利再次獲取這把鎖如果是不可重入鎖,那么第二次獲得鎖時(shí),自己也會被鎖擋住,需要的朋友可以參考下
    2023-12-12
  • Java中的FileInputStream 和 FileOutputStream 介紹_動力節(jié)點(diǎn)Java學(xué)院整理

    Java中的FileInputStream 和 FileOutputStream 介紹_動力節(jié)點(diǎn)Java學(xué)院整理

    FileInputStream 是文件輸入流,它繼承于InputStream。FileOutputStream 是文件輸出流,它繼承于OutputStream。接下來通過本文給大家介紹Java中的FileInputStream 和 FileOutputStream,需要的朋友可以參考下
    2017-05-05
  • MyBatis-Plus實(shí)現(xiàn)2種分頁方法(QueryWrapper查詢分頁和SQL查詢分頁)

    MyBatis-Plus實(shí)現(xiàn)2種分頁方法(QueryWrapper查詢分頁和SQL查詢分頁)

    本文主要介紹了MyBatis-Plus實(shí)現(xiàn)2種分頁方法,主要包括QueryWrapper查詢分頁和SQL查詢分頁,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-08-08
  • java線性表排序示例分享

    java線性表排序示例分享

    這篇文章主要介紹了java線性表排序示例,需要的朋友可以參考下
    2014-03-03
  • spring boot如何使用spring AOP實(shí)現(xiàn)攔截器

    spring boot如何使用spring AOP實(shí)現(xiàn)攔截器

    本篇文章主要介紹了spring boot如何使用spring AOP實(shí)現(xiàn)攔截器,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • 詳解java并發(fā)之重入鎖-ReentrantLock

    詳解java并發(fā)之重入鎖-ReentrantLock

    這篇文章主要介紹了java并發(fā)之重入鎖-ReentrantLock,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Spring Aop組成部分及實(shí)現(xiàn)步驟

    Spring Aop組成部分及實(shí)現(xiàn)步驟

    面向切面編程,是對面向?qū)ο缶幊痰囊环N補(bǔ)充,是一種編程思想,是對某一類的事情的集中處理,這篇文章主要介紹了Spring Aop組成部分及實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2023-08-08
  • Netty實(shí)現(xiàn)簡易版的RPC框架過程詳解

    Netty實(shí)現(xiàn)簡易版的RPC框架過程詳解

    這篇文章主要為大家介紹了Netty實(shí)現(xiàn)簡易版的RPC框架過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02

最新評論