电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

springboot自動配置原理解析

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

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

開始

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

首先創建一個springboot工程用來測試,然后在pom文件中引入springboot-starter-redis的啟動器依賴

<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

然后,在啟動類中注入redisTemplate類,redisTemplate為spring官方提供的對redis底層開發包(例如jedis)進行了深度封裝的組件,使用redisTemplate可以優雅的操作redis。我在啟動類中寫了一個測試方法,向redis寫入一條數據

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

運行這個方法,打開redis客戶端可以看到值已經寫入了

springboot自動配置原理解析

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

首先我們來看,springboot啟動類上都有一個@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這個注解是由一系列的注解組合而成,這其中最重要的是@EnableAutoConfiguration和@ComponentScan,@ComponentScan的意思就是組件掃描注解,這個注解會自動注入所有在主程序所在包下的組件。比@ComponentScan注解更重要的就是@EnableAutoConfiguration注解了,這個注解的含義就是開啟自動裝配,直接把bean裝配到ioc容器中,@EnableAutoConfiguration也是一個組合注解,我們點進去看一下

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

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

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

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

@Import注解用來導入@Configuration注解的配置類、聲明@Bean注解的bean方法、導入ImportSelector的實現類或導入ImportBeanDefinitionRegistrar的實現類,這里這個AutoConfigurationPackages.Registrar.class就是ImportBeanDefinitionRegistrar的實現類,來看下源碼

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {//metadata是注解的元信息 registry是bean定義的注冊器@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //把注解所在的包下所有的組件都進行注冊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) {//首先判斷這個bean有沒有被注冊if (registry.containsBeanDefinition(BEAN)) {//獲取bean定義BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);//通過bean定義獲取構造函數值ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();//給構造函數添加參數值constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));}else {//一個新的bean定義GenericBeanDefinition beanDefinition = new GenericBeanDefinition();//設置beanClass為beanPackages類型beanDefinition.setBeanClass(BasePackages.class);beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//bean注冊registry.registerBeanDefinition(BEAN, beanDefinition);}}

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

@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}//加載元數據AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);//獲得自動裝配的實體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);//去除重復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,我們來看下這個方法

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

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

springboot自動配置原理解析

springboot自動配置原理解析

我們看到文件中有一行注釋這Auto configure,表示這些都是自動配置相關的類,這里我們不得不說spring框架真的是強大,這里面居然有100多個自動配置類,我們找到redis有關的自動配置類

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

這里我們需要的肯定是第一個自動配置類,我們點進去看看

@Configuration//條件注解,某個class位于類路徑上,才會實例化一個Bean,這個類是redis操作的類@ConditionalOnClass(RedisOperations.class)//使得@ConfigurationProperties 注解的類生效,這個類是配置redis屬性的類@EnableConfigurationProperties(RedisProperties.class)//導入一些配置@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration {@Bean//僅僅在當前上下文中不存在某個對象時,才會實例化一個Bean,這個就是spring默認的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;}}

我們在application.properties中配置的redis屬性,其實就是設置到了這個類中

//前綴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默認的redisTemplate操作redis的話,存到redis里的數據對我們的閱讀不友好,我們看不懂,那是因為redisTemplate中默認用了jdk自帶的序列化器

springboot自動配置原理解析

要想讓數據變成我們能看得懂的樣子,我們需要替換掉redisTempalte默認的序列化器,現在我就來實操一下,寫一個配置類

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

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

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

springboot自動配置原理解析

我們看到,序列化器已經生效了,鍵值對已經是我們能看得懂的了。

總結

通過springboot整合redis的過程,我帶大家分析了一下springboot的自動配置原理,基本上市面上流行的組件可以和spring整合的spring官方都有starter,引入starter,配合springboot的自動配置,基本上可以做到只需要幾行屬性的配置加上類的注入,就可以使用了,spring框架博大精深,還有很多很多東西需要學習,有時間我再給大家分享,望大家多多支持,謝謝。

以上就是springboot自動配置原理解析的詳細內容,更多關于springboot自動配置原理的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
主站蜘蛛池模板: 雄松华章(广州华章MBA)官网-专注MBA/MPA/MPAcc/MEM辅导培训 | 伺服电机维修、驱动器维修「安川|三菱|松下」伺服维修公司-深圳华创益 | 控显科技 - 工控一体机、工业显示器、工业平板电脑源头厂家 | 兰州牛肉面加盟,兰州牛肉拉面加盟-京穆兰牛肉面 | 陕西视频监控,智能安防监控,安防系统-西安鑫安5A安防工程公司 | 半容积式换热器_北京浮动盘管换热器厂家|北京亿丰上达 | 自动配料系统_称重配料控制系统厂家| 线材成型机,线材折弯机,线材成型机厂家,贝朗自动化设备有限公司1 | 中医治疗皮肤病_潍坊银康医院「山东」重症皮肤病救治平台 | 三板富 | 专注于新三板的第一垂直服务平台 | 清洁设备_洗地机/扫地机厂家_全自动洗地机_橙犀清洁设备官网 | 环压强度试验机-拉链拉力试验机-上海倾技仪器仪表科技有限公司 | 不锈钢发酵罐_水果酒发酵罐_谷物发酵罐_山东誉诚不锈钢制品有限公司 | 除尘器布袋骨架,除尘器滤袋,除尘器骨架,电磁脉冲阀膜片,卸灰阀,螺旋输送机-泊头市天润环保机械设备有限公司 | 防爆大气采样器-防爆粉尘采样器-金属粉尘及其化合物采样器-首页|盐城银河科技有限公司 | 中空玻璃生产线,玻璃加工设备,全自动封胶线,铝条折弯机,双组份打胶机,丁基胶/卧式/立式全自动涂布机,玻璃设备-山东昌盛数控设备有限公司 | 柔性测斜仪_滑动测斜仪-广州杰芯科技有限公司 | 杭州火蝠电商_京东代运营_拼多多全托管代运营【天猫代运营】 | 正压密封性测试仪-静态发色仪-导丝头柔软性测试仪-济南恒品机电技术有限公司 | 齿轮减速机电机一体机_齿轮减速箱加电机一体化-德国BOSERL蜗轮蜗杆减速机电机生产厂家 | 精密模具加工制造 - 富东懿| 粒米特测控技术(上海)有限公司-测功机_减速机测试台_电机测试台 | 铝箔-铝板-花纹铝板-铝型材-铝棒管-上海百亚金属材料有限公司 | 丁基胶边来料加工,医用活塞边角料加工,异戊二烯橡胶边来料加工-河北盛唐橡胶制品有限公司 | CXB船用变压器-JCZ系列制动器-HH101船用铜质开关-上海永上船舶电器厂 | 广西绿桂涂料--承接隔热涂料、隔音涂料、真石漆、多彩仿石漆等涂料工程双包施工 | 河南卓美创业科技有限公司-河南卓美防雷公司-防雷接地-防雷工程-重庆避雷针-避雷器-防雷检测-避雷带-避雷针-避雷塔、机房防雷、古建筑防雷等-山西防雷公司 | 压缩空气检测_气体_水质找上海京工-服务专业、价格合理 | 碳钢法兰厂家,非标法兰,定制异型,法兰生产厂家-河北九瑞管道 | 机房监控|动环监控|动力环境监控系统方案产品定制厂家 - 迈世OMARA | 化妆品加工厂-化妆品加工-化妆品代加工-面膜加工-广东欧泉生化科技有限公司 | 工业铝型材生产厂家_铝合金型材配件批发精加工定制厂商 - 上海岐易铝业 | 酸度计_PH计_特斯拉计-西安云仪 纯水电导率测定仪-万用气体检测仪-低钠测定仪-米沃奇科技(北京)有限公司www.milwaukeeinst.cn | 巩义市科瑞仪器有限公司| arch电源_SINPRO_开关电源_模块电源_医疗电源-东佑源 | 专业音响设备_舞台音响设备_会议音响工程-首选深圳一禾科技 | Magnescale探规,Magnescale磁栅尺,Magnescale传感器,Magnescale测厚仪,Mitutoyo光栅尺,笔式位移传感器-苏州连达精密量仪有限公司 | 不锈钢管件(不锈钢弯头,不锈钢三通,不锈钢大小头),不锈钢法兰「厂家」-浙江志通管阀 | 仿真茅草_人造茅草瓦价格_仿真茅草厂家_仿真茅草供应-深圳市科佰工贸有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 手持式3d激光扫描仪-便携式三维立体扫描仪-北京福禄克斯 |