日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

springboot自動(dòng)配置原理解析

瀏覽:209日期:2023-03-16 15:12:38
前言

小伙伴們都知道,現(xiàn)在市面上最流行的web開發(fā)框架就是springboot了,在springboot開始流行之前,我們都用的是strust2或者是springmvc框架來開發(fā)web應(yīng)用,但是這兩個(gè)框架都有一個(gè)特點(diǎn)就是配置非常的繁瑣,要寫一大堆的配置文件,spring在支持了注解開發(fā)之后稍微有些改觀但有的時(shí)候還是會(huì)覺得比較麻煩,這個(gè)時(shí)候springboot就體現(xiàn)出了它的優(yōu)勢,springboot只需要一個(gè)properties或者yml文件就可以簡化springmvc中在xml中需要配置的一大堆的bean,這就是因?yàn)閟pringboot有自動(dòng)配置,那么springboot自動(dòng)配置的原理是什么呢,今天我們就來通過源碼分析一下springboot的自動(dòng)配置原理

開始

我以springboot整合redis為例,來向大家分析springboot的自動(dòng)配置原理

首先創(chuàng)建一個(gè)springboot工程用來測試,然后在pom文件中引入springboot-starter-redis的啟動(dòng)器依賴

<dependencies><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.1.7.RELEASE</version></dependency></dependencies>

然后,在application.properties中配置redis屬性

spring.redis.port=6379spring.redis.host=localhostspring.redis.database=0

然后,在啟動(dòng)類中注入redisTemplate類,redisTemplate為spring官方提供的對(duì)redis底層開發(fā)包(例如jedis)進(jìn)行了深度封裝的組件,使用redisTemplate可以優(yōu)雅的操作redis。我在啟動(dòng)類中寫了一個(gè)測試方法,向redis寫入一條數(shù)據(jù)

@RequestMapping('/redistest') public String test(){redisTemplate.opsForSet().add('aaaaa','123456');return 'OK'; }

運(yùn)行這個(gè)方法,打開redis客戶端可以看到值已經(jīng)寫入了

springboot自動(dòng)配置原理解析

先拋開這里的鍵和值讓人看不懂的問題,大家是不是覺得springboot整合redis要比普通的springmvc整合redis簡單多了?我只配置了redis的連接地址,端口號(hào),注入了redisTemplate,就能開始操作redis了,那么springboot底層到底做了些什么使得整合變得如此的簡單了呢。

首先我們來看,springboot啟動(dòng)類上都有一個(gè)@SpringbootApplication注解,那么這個(gè)注解是起什么作用的呢,讓我們點(diǎn)進(jìn)去看一下

@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è)注解是由一系列的注解組合而成,這其中最重要的是@EnableAutoConfiguration和@ComponentScan,@ComponentScan的意思就是組件掃描注解,這個(gè)注解會(huì)自動(dòng)注入所有在主程序所在包下的組件。比@ComponentScan注解更重要的就是@EnableAutoConfiguration注解了,這個(gè)注解的含義就是開啟自動(dòng)裝配,直接把bean裝配到ioc容器中,@EnableAutoConfiguration也是一個(gè)組合注解,我們點(diǎn)進(jìn)去看一下

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration

這個(gè)地方我們主要看@AutoConfigurationPackage和@Import(AutoConfigurationImportSelector.class)兩個(gè)注解,首先來看@AutoConfigurationPackage注解

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

這個(gè)注解主要是獲取我們注解所在包下的組件去進(jìn)行注冊(cè),大家看到這個(gè)@Import注解,那么這個(gè)注解是什么含義呢,

@Import注解用來導(dǎo)入@Configuration注解的配置類、聲明@Bean注解的bean方法、導(dǎo)入ImportSelector的實(shí)現(xiàn)類或?qū)隝mportBeanDefinitionRegistrar的實(shí)現(xiàn)類,這里這個(gè)AutoConfigurationPackages.Registrar.class就是ImportBeanDefinitionRegistrar的實(shí)現(xiàn)類,來看下源碼

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {//metadata是注解的元信息 registry是bean定義的注冊(cè)器@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //把注解所在的包下所有的組件都進(jìn)行注冊(cè)register(registry, new PackageImport(metadata).getPackageName());}@Overridepublic Set<Object> determineImports(AnnotationMetadata metadata) {return Collections.singleton(new PackageImport(metadata));}}public static void register(BeanDefinitionRegistry registry, String... packageNames) {//首先判斷這個(gè)bean有沒有被注冊(cè)if (registry.containsBeanDefinition(BEAN)) {//獲取bean定義BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);//通過bean定義獲取構(gòu)造函數(shù)值ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();//給構(gòu)造函數(shù)添加參數(shù)值constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));}else {//一個(gè)新的bean定義GenericBeanDefinition beanDefinition = new GenericBeanDefinition();//設(shè)置beanClass為beanPackages類型beanDefinition.setBeanClass(BasePackages.class);beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//bean注冊(cè)registry.registerBeanDefinition(BEAN, beanDefinition);}}

接下來就是@Import(AutoConfigurationImportSelector.class)這個(gè)注解,我們來看看AutoConfigurationImportSelector這個(gè)類,這個(gè)類是我們自動(dòng)裝配的導(dǎo)入選擇器,首先看這個(gè)類的第一個(gè)方法,其實(shí)也就是這個(gè)類的核心方法

@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}//加載元數(shù)據(jù)AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);//獲得自動(dòng)裝配的實(shí)體AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}//獲得屬性AnnotationAttributes attributes = getAttributes(annotationMetadata);//獲得候選的配置類,核心方法List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//去除重復(fù)configurations = removeDuplicates(configurations);//獲得排除的配置Set<String> exclusions = getExclusions(annotationMetadata, attributes);//檢查排除的配置checkExcludedClasses(configurations, exclusions);//排除configurations.removeAll(exclusions);configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);}

在這部分中,核心方法是getCandidateConfigurations,我們來看下這個(gè)方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {//從工廠中獲取自動(dòng)配置類List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());//這句斷言很重要,告訴了我們工廠是去哪里找自動(dòng)配置類的,這里顯然META-INF/spring.factories是一個(gè)路徑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;}

那我們就找一下這個(gè)路徑,去哪里找呢,我們看到這個(gè)類的包是org.springframework.boot.autoconfigure;那我們就到這個(gè)包的位置去找這個(gè)spring.factories,果不其然,我們點(diǎn)開這個(gè)文件

springboot自動(dòng)配置原理解析

springboot自動(dòng)配置原理解析

我們看到文件中有一行注釋這Auto configure,表示這些都是自動(dòng)配置相關(guān)的類,這里我們不得不說spring框架真的是強(qiáng)大,這里面居然有100多個(gè)自動(dòng)配置類,我們找到redis有關(guān)的自動(dòng)配置類

org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,

這里我們需要的肯定是第一個(gè)自動(dòng)配置類,我們點(diǎn)進(jìn)去看看

@Configuration//條件注解,某個(gè)class位于類路徑上,才會(huì)實(shí)例化一個(gè)Bean,這個(gè)類是redis操作的類@ConditionalOnClass(RedisOperations.class)//使得@ConfigurationProperties 注解的類生效,這個(gè)類是配置redis屬性的類@EnableConfigurationProperties(RedisProperties.class)//導(dǎo)入一些配置@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration {@Bean//僅僅在當(dāng)前上下文中不存在某個(gè)對(duì)象時(shí),才會(huì)實(shí)例化一個(gè)Bean,這個(gè)就是spring默認(rèn)的redisTemplate@ConditionalOnMissingBean(name = 'redisTemplate')public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);return template;}@Bean@ConditionalOnMissingBeanpublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {StringRedisTemplate template = new StringRedisTemplate();template.setConnectionFactory(redisConnectionFactory);return template;}}

我們?cè)赼pplication.properties中配置的redis屬性,其實(shí)就是設(shè)置到了這個(gè)類中

//前綴spring.redis@ConfigurationProperties(prefix = 'spring.redis')public class RedisProperties {/** * Database index used by the connection factory. */private int database = 0;/** * Connection URL. Overrides host, port, and password. User is ignored. Example: * redis://user:password@example.com:6379 */private String url;/** * Redis server host. */private String host = 'localhost';/** * Login password of the redis server. */private String password;/** * Redis server port. */private int port = 6379;/** * Whether to enable SSL support. */private boolean ssl;/** * Connection timeout. */private Duration timeout;private Sentinel sentinel;private Cluster cluster;private final Jedis jedis = new Jedis();private final Lettuce lettuce = new Lettuce();}

我們前面說了,用了spring默認(rèn)的redisTemplate操作redis的話,存到redis里的數(shù)據(jù)對(duì)我們的閱讀不友好,我們看不懂,那是因?yàn)閞edisTemplate中默認(rèn)用了jdk自帶的序列化器

springboot自動(dòng)配置原理解析

要想讓數(shù)據(jù)變成我們能看得懂的樣子,我們需要替換掉redisTempalte默認(rèn)的序列化器,現(xiàn)在我就來實(shí)操一下,寫一個(gè)配置類

@Configurationpublic class RedisConfig { //這里的上下文已經(jīng)有了自定義的redisTemplate,所以默認(rèn)的redisTemplate不會(huì)生效 @Bean public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>();//設(shè)置自定義序列化器redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate; }}

然后我改寫一下測試方法,一起來看結(jié)果

public String test(){redisTemplate.opsForSet().add('ffffff','55555555');return 'OK'; }

springboot自動(dòng)配置原理解析

我們看到,序列化器已經(jīng)生效了,鍵值對(duì)已經(jīng)是我們能看得懂的了。

總結(jié)

通過springboot整合redis的過程,我?guī)Т蠹曳治隽艘幌聅pringboot的自動(dòng)配置原理,基本上市面上流行的組件可以和spring整合的spring官方都有starter,引入starter,配合springboot的自動(dòng)配置,基本上可以做到只需要幾行屬性的配置加上類的注入,就可以使用了,spring框架博大精深,還有很多很多東西需要學(xué)習(xí),有時(shí)間我再給大家分享,望大家多多支持,謝謝。

以上就是springboot自動(dòng)配置原理解析的詳細(xì)內(nèi)容,更多關(guān)于springboot自動(dòng)配置原理的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
视频一区二区三区在线| 亚洲精品亚洲人成在线观看| 97精品一区二区| 亚洲欧美日韩国产综合精品二区 | 国产成人久久精品麻豆二区 | 国产精品婷婷| 精品久久免费| 视频一区中文字幕精品| 欧美三级精品| 日韩一区中文| 国产精品99免费看| 电影91久久久| 国产极品嫩模在线观看91精品| 激情欧美国产欧美| 日韩综合在线| 国产精品66| 亚洲精品福利| 先锋影音久久久| 欧美va天堂| 国产精品久久观看| 精品亚洲成人| 国产精品日韩精品中文字幕| 在线一区二区三区视频| 红杏一区二区三区| 久久精品一区二区国产| 国产精品美女久久久久久不卡| 亚洲天堂久久| 一本综合精品| 国产一区二区三区黄网站| 久久蜜桃av| 亚洲乱码久久| 久久精品人人| 亚洲精品无播放器在线播放| 国产亚洲精品久久久久婷婷瑜伽| 午夜电影亚洲| 日韩精品导航| 日韩理论视频| 石原莉奈在线亚洲三区| 欧美激情在线精品一区二区三区| 国内精品麻豆美女在线播放视频| 日韩国产综合| 日韩和欧美一区二区| 欧美精品高清| 日本va欧美va精品| 日韩欧美午夜| 日韩国产欧美三级| 99久久精品网| 美女av一区| 亚洲香蕉久久| 日韩免费小视频| 7777精品| 丝袜脚交一区二区| 蜜桃视频在线网站| 国产精品欧美三级在线观看| 亚洲精品2区| 91福利精品在线观看| 国产精品三上| 日韩伦理一区| 日韩一区二区三区四区五区| 9999国产精品| 日韩不卡在线观看日韩不卡视频| 国产成人精品一区二区三区在线| 99re国产精品| 国产精品2023| 今天的高清视频免费播放成人| 亚洲免费一区三区| 亚洲成人精品| 国产精品一国产精品| 鲁大师成人一区二区三区| 国产一区二区三区不卡av| 午夜日本精品| av高清不卡| 国产精品tv| 日韩和欧美一区二区| 蘑菇福利视频一区播放| 午夜影院一区| 国产suv精品一区| 麻豆一区二区三区| 国产色噜噜噜91在线精品| 男人的天堂久久精品| 日韩午夜黄色| 国产一区日韩一区| 麻豆网站免费在线观看| 国产一区二区视频在线看| 国产精品啊啊啊| 日韩在线视频一区二区三区| 午夜在线一区二区| 伊人久久婷婷| 91九色精品国产一区二区| 999精品色在线播放| 日韩亚洲一区在线| 秋霞影视一区二区三区| 91成人超碰| 99在线|亚洲一区二区| 日韩中文字幕1| 亚欧洲精品视频在线观看| 亚洲影视一区二区三区| 日韩和欧美一区二区| 国产精品一区二区精品| 国产精品久久久久久妇女| 久久狠狠亚洲综合| 久久97视频| 桃色一区二区| 亚洲专区一区| 国产精品视频首页| 日韩成人三级| 欧美在线综合| 国产美女久久| 91精品韩国| 亚洲精品在线a| 欧美亚洲自偷自偷| 国产成人免费| 九九综合九九| 日韩av一区二区三区四区| 91亚洲国产成人久久精品| 欧美日韩免费观看视频| 午夜在线播放视频欧美| 国产探花一区| 久久国产主播| 日本精品在线播放| 日韩精品不卡一区二区| 一级欧美视频| 中文字幕色婷婷在线视频 | 久久性天堂网| 久久久久97| 性一交一乱一区二区洋洋av| 国产日产一区| 亚洲精品一区三区三区在线观看| 日韩影院精彩在线| 精品日韩在线| 免费视频一区二区| 夜久久久久久| 精品久久亚洲| 日本亚洲最大的色成网站www | 88久久精品| 国产免费成人| 樱桃视频成人在线观看| 88久久精品| 视频一区视频二区在线观看| 久久高清精品| а√天堂8资源在线| 国产精品久久久久77777丨| 欧美亚洲国产激情| 麻豆mv在线观看| 精品一区二区三区中文字幕在线| 日韩精品欧美大片| 免费黄网站欧美| 蜜臀久久久99精品久久久久久| 久久天堂精品| 久久久天天操| 99久久精品网站| 久久久久国产一区二区| 日韩精品欧美激情一区二区| 在线精品亚洲欧美日韩国产| 久久中文字幕一区二区三区| 国产欧美激情| 韩日一区二区| 美女久久精品| 日韩精品dvd| 蜜桃国内精品久久久久软件9| 久久久国产精品一区二区中文| 樱桃视频成人在线观看| 日韩欧美在线中字| 激情五月综合| 亚洲欧美专区| 国产精久久久| av在线资源| 黄色亚洲大片免费在线观看| 免费精品视频| 日本色综合中文字幕| 国产精品超碰| 97精品国产一区二区三区 | 香蕉人人精品| 亚洲午夜久久| 欧美激情精品| 亚洲精品99| 日韩国产91| 日韩网站中文字幕| 日韩影院精彩在线| 国产亚洲一区二区三区啪| 高清日韩欧美| 天堂成人国产精品一区| 国产三级一区| 99精品在线观看| 日韩成人在线看| 91青青国产在线观看精品| 久久午夜影视| 在线天堂中文资源最新版| 蜜臀av一区二区三区| 四虎国产精品免费观看| 亚洲人成网站在线在线观看| 97人人精品| 日韩精品免费视频一区二区三区| 国产+成+人+亚洲欧洲在线| 亚洲色图国产| 蜜桃成人av| 视频在线不卡免费观看| 亚洲精品乱码日韩| 免费在线观看一区| 国产视频一区欧美|