自动装配机制

简介: 本文深入解析SpringBoot自动装配机制,从@SpringBootApplication注解入手,剖析其组合注解的实现原理。重点讲解@EnableAutoConfiguration如何通过@Import和SpringFactoriesLoader加载自动配置类,结合@ComponentScan、@SpringBootConfiguration等完成组件扫描与注册,实现“零配置”下的自动化装配,提升开发效率。

自动装配机制

前言

@TargeT(ELeMenTTypeTYP)

ReTention(RetentionPolicy.RUNTIME)

Documented

@Inherited

@SpringBootconfiguration

@Enableautoconfiguration

LOPORGMSANXSORLTSAUTERUPEFITRYPEUSTHCSYEXCFITECLASS

Ftter(typeFLtertYDcUSTOMutoonrttOXLUFLTeRCLASS))

public@interfaceSpringBootApplication


SpringBoot主启动类被@SpringBootApplication所修饰,点击进去该注解,出现上图,会发现其为组合注解,本章节将会基于注解进行解释其自动装配在源码层面是怎么实现的,完整的注解调用链路如下图所示:

@Inherited

@Target

@Documented

@Retention

AutoConfigurationExcludeFilter

TypeExcludeFilter

ComponentScan

@Configuration

SpringBootConfiguration

@Import(AutoConfigurationImportSelector.class)

@Import(AutoConfigurationPackages.Registrar.class)

@AutoConfigurationPackage

EnableAutoConfiguration

SpringBootApplication

1.元注解
@Target注解

注解的作用目标
@Target(ElementType.TYPE)                                           //接口、类、枚举、注解
@Target(ElementType.FIELD)                                         //字段、枚举的常量
@Target(ElementType.METHOD)                                   //方法
@Target(ElementType.PARAMETER)                              //方法参数
@Target(ElementType.CONSTRUCTOR)                        //构造函数
@Target(ElementType.LOCAL_VARIABLE)                     //局部变量
@Target(ElementType.ANNOTATION_TYPE)                //注解
@Target(ElementType.PACKAGE)                                 //包    
@Retention注解

修饰注解,是注解的注解,称为元注解
SOURCE,     // 编译器处理完Annotation后不存储在class中  
CLASS,       // 编译器把Annotation存储在class中,这是默认值  
RUNTIME  // 编译器把Annotation存储在class中,可以由虚拟机读取,反射需要
@Documented注解

这个Annotation可以被写入javadoc

上述三个元注解也是实现自定义注解的基础,不是很清楚的可以先看这篇:自定义注解
@Inherited 注解

作用先看这篇:@Inherited作用,简而言之:
@SpringBootApplication注解被@Inherited修饰,则SpringBoot主启动类也就具备了@SpringBootApplication注解的:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
2.@ComponentScan注解

这个注解原来在SpringFramework中比较常见,而且其出现位置为配置文件:spring配置文件的applicationContext.xml或者springmvc的配置文件中,用来标识:扫描的包路径,这样就可以将我们定义的注解扫描进去。
在SpringBoot中,其关键作用是:默认扫描当前配置类所在包及子包下的所有组件, exclude 属性会将主启动类、自动配置类屏蔽掉

AutoConfigurationExcludeFilter

TypeExcludeFilter

@ComponentScan

2.1 TypeExcludeFilter注解

publtccassTYPeExCLFLtrimpLEmeSTYPEFLERBAnFacTorYWaRE

privateBeanFactorybeanFactory;

privatecollectionTypeExcludeFilterdelegates;

aoverride

pubttcVodseteanFactoryeanfactorybeanfactory)throwsBeansException

this.beanfactorybeanFactory;

aOverride

PADTICBOLCERDARCNGAGTRDGRRCROURLARAREMETOURLARAGGRFACTOYTCODTRCOUGRFACTOMY

throwSIOException

tclass()TypeExcludeFiuter.class)

if(this.beanfactoryinstanceofListableBeanfactorygeca

for(TypeExcludeFilterdelegate:getDelegates))

tf(delegate.match(metadatareadermdco

returntrue;

returnfalse;


其核心代码简单PO出,依赖BeanFactory,这个BeanFactory就是SpringFramework接口体系中的顶层,定义了基本的方法,如:getBean,containsBean,isSingleton,getType,isTypeMatch等。如下图(体系要比这个更丰富,推荐大家自己在Idea中生成查看,看SpringBoot源码的前提,建议先看Spring源码):

FunclionalinLerface

ResourceLoader

BEanFacLory

6ResourcePatternResolver

6+MesSageSource

EnvironmentCapable

ListableBeanFactory

ApplicationEventPublisher

HicrarchicaibcanFactory

AoplicationContext

PEWINeByFiLzs


TypeExcludeFilter核心方法为match(),其关键作用在于:拓展组件的过滤,提供一种扩展机制,能让我们向IOC容器中注册一些自定义的组件过滤器,以在包扫描的过程中过滤它们。会从 BeanFactory 中获取所有类型为 TypeExcludeFilter 的组件,去执行自定义的过滤方法。
2.2 AutoConfigurationExcludeFilter注解

LASSAUTOCOOFIGURATLONEXILTERLEMENTSTYPEFILTERBEANCLASSLARE

public

privateClassLoaderbeanclassLoader;

privatevolatileListstringuonfguration;

@Override

PublicVodsetBeancLasda

this.beanclassLoader-beanclassLoader;

@Override

ymetadataReaderFactory)

PULCBLeARdEmetadatReadERMetadRedERFaCTORY

throwsIoException

TetuRNtsConfigurationmEtadtReadeR)iAutoconfigurationetadtReade)

PrivatebooteanisconigurationeadteademetadataReader)

retummetadgtskeader.getmmoatiomeadata.ma

privatebooleanisAutoconfigurationMtdtReadermetadataReadeR)

RETURSERAUTOSOITLOURARIOMSOTALNSETADTREERER9ETCLASSTADTAETCLASSMMEDD;


其核心方法和TypeExcludeFilter一样,match()方法,但是实现有所区别,AutoConfigurationExcludeFilter的核心是:判断是否是一个配置类,且同时是否是一个自动配置的配置类
2.3 问题:SpringBoot怎么过滤不需要的组件

【面试题】:Spring IOC容器在boot中也是存在的对吧,那有一些Bean我不想在启动时就注入IOC容器,这种情况有遇到过吗?

【个人理解】:目前还没遇到,不过要是实现的话,在启动类上加上@ComponentScan注解,在value中写上指定的:*.class是可以实现的【参见2.4小结】,或继承TypeExcludeFilter ,重写match方法,如默认会加载com.test.TestService这个bean,则重写的方法中,
或者直接在boot配置文件中添加,其是支持的【但是我没细究如何配置,这个百度下应该就有】,如下:

pActiveoAutoconfiRurationspringtranework.boot.autoconrece

AopAutoConfigurationoRg.Springframework.bootautoconfigue

ArtemisAutoconfiguration(org.springfrawework.boot.autoconfigurejns.atemi)

BatchautoconfigurationCorg.springframework.boot.autoconfigurebat)

CacheAutoconfigurationorg.springframework.boot.autoconfigure.cache)

CassandrahAutoconfifurationakotu

CassandraDataAutoconfiguration

org.springframework.boot.autoconfigure.data.ca.

CassandraReactiveDataiutoconfiqurationspingtraneuork.bootutoconure

CasandraReactiveRpotoieutontio

assandraReposttoriesAutoconfizurtionk

CientHttpcomectorAutoconfizurationoingramwrkbucoue

ELGwIGTOEEEEEEtBCOM

spring.autoconfigure.exclude


2.4 小结

上述之后我们都能知道两个Exclude都有match方法,但是匹配什么?过滤什么?至少我在第一次看的时候还是很懵的,目前我的认知总结如下,可能不是很准确,提供出来给大家参考一下:
@ComponentScan注解会扫描Bean完成IOC注入,但是有一部分我们是不需要注入进IOC容器的,那么这种场景下我们就可以借助于我们这一小章节的注解进行实现,其实现方法就是:

@SpringBootapplication

OPOERSARCRLWLTESOPORSCARTEYPEFATERYPEASSTOUMETREC

ITestBean.class万3)

publicclassFrameworkSpringApplication

publicstaticvoidmain(stringljargs)

SpringAppltcationu(mewokingpplcation


import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {TestBean.class})})
这种方式是官方给的一个参考方式,但是我们也可以清楚的看到弊端:仅适用于少量的,如果需要规避的扫描类很多,这个classes将会变的非常冗杂,当然也有很多解决方案,如继承TypeExcludeFilter ,重写match方法,更多方式自行百度下就行。
关于@AutoConfigurationExcludeFilter,能搜到的资料很少,区别就在于多了一部分AutoConfiguration,所以我目前的认知是:二者都能用来处理组件过滤,但是是TypeFilter接口的两种实现,一种主要服务于主启动类组件,一种服务于自动配置的组件,二者结合实现一个完整的组件过滤。

FunctionalInterface

Aware

BeanClassLoaderAware

BeanFactoryAware

Typerilter

TypeExcludeFilter

AutoConfigurationExcludefilter

PowEredbyYFiles


上图的BeanFactoryAware,BeanClassLoaderAware在Spring IOC容器中比较常见,也是Spring的Bean生命周期中会遇到的组件,这里就不再赘述,有需要的百度学习下即可,贴个简单的IOC接口体系(实际要更丰富)。

BeanFactory

AutowireCapableBeanFactory

ApplicationConText

ApplicationContextassertProvider

AssertableReactivewebApplicationConText

AssertableApplicationContext

AssertablewebApplicationContext

Powereabywaies


3.@SpringBootConfiguration注解

@Target(ELemenType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

aConfiguration

public@interfaceSpringBootconfiguration

1大太

@since2.2

Configuration.class)

@ALiasFor(annotation

default

booleanproxyBeanMethods(

true;


官方给的解释也是:@SpringBootConfiguration 是对 @Configuration注解(这个我们可能就比较熟悉了,不了解的参考:@Configuration)的一种封装,在上图我们也可看出,其核心作用是:标注在配置类上,且是主启动类(如果@Configuration标注就不必强调是主启动类),基于这个注解,其所在的包路径位置获取之后EnableAutoConfiguration(第4节详细论述)注解扫描的依据,进而扫描出配置文件。
这里也说明了为什么SpringBoot的主启动类,我们是放在包的最外层,因为只有这样,我们的basePackage才能够获取到全部组件。
4.@EnableAutoConfiguration注解

我们简单了解下SpringFramework的装配吧:

模块装配 @EnableXXX 与 @Import (Spring3.1+)

@Controller

@Repository

@Service

模式注解@Component(Spring2.5+)

配置类 @Configuration 与 @Bean(Spring3.0+)

SpringFramework手动装配

其中:@Repository,@Service,@Controller为Component的衍生注解,后面配置实现可以参考这里:链接
【SpringFramework总结】
基于以上三种任意一种方式(我们常用的还是第一种注解模式),就可以实现对应的装配机制,所谓的装配就是告诉我们的Spring我们要用哪些Bean,顶层的BeanFactory的子类ApplicationContext帮我们实现底层细节【IOC接口体系2.3小结有简略版】,IOC容器帮我们完成Bean的注入实现,其缓存机制帮我们规避循环依赖,以实现一个装配体系。

【SpringBoot自动装配开始】

这里我觉得还是直接拷贝其官方解释更好,也顺便翻译一下(个人理解可能会有偏差)
其完整代码如下所示,可看到它也是一个组合注解,主要包括4个元注解+2个自定义注解,所以这两个注解应该就是帮我们实现自动化配置的核心所在了。

@Target(ELementType.TYPE)

CRetention(RetentionPolicy.RUNTIMe)

@Documented

@Inherited

@AutoConfigurationPackage

@Import(utoconfigurationImportselector.class)

public@interfaceEnabteAutoconfiguration

"spring.boot.eableautoconfiguration";

stringENABLED-OVERRIDE_PROOERTY

排除特定的自动店宜类,使它们水远不会被应用

@return返回要打除的英

classi_0exclude)defaultl;

大*

并险特定的自动配置类名,使它们就水远不会出现.

返回麦捕除的类名

@return

1.3.0

@since

stringljexcludename)defaultl;


4.1 @AutoConfigurationPackage注解概述

@Target(ELemeType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

QInherited

Import(AutoConfigurationPackagesRegistrar.class)

publicinterfaceAutoconfigurationPackage


这个注解看起来就比较简单了,没有特别的代码,也只有4个元注解+1个自定义注解,但是可以看到这个注解@Import和上面的@EnableAutoConfiguration内部的value还是不一样的,区别在4.2讲解。
@EnableAutoConfiguration:AutoConfigurationImportSelector.class
@AutoConfigurationPackage:AutoConfigurationPackages.Registrar.class
前面我们也有提到,主启动类必须放在所有自定义组件的包的最外层,以保证Spring能扫描到它们,就是@AutoConfigurationPackage发挥的作用,【作用小结】:保证Spring扫描到所有子包,完成资源的加载.
其实现原理如下4.1.1:
4.2 AutoConfigurationPackage实现原理

在4.1的图可看到,他引入了一个@Import注解,这个注解引入了AutoConfigurationPackages.Registrar

存储来白导入盘且的根包.

RegistrarimplementsImpotBeanDeftnttionegseaem

staticclass

COverrtde

puhicvodregtsteremtto

regtster(regtstryewPackageimport(metadata).geckageame);

@Override

publtcsetcobjectdeterminemotsotionedtad)

returnCottections.singeoewackagem;


Register 实现了 ImportBeanDefinitionRegister 接口,通过它实现向IOC容器手动注册组件,在重写的 registerBeanDefinitions 方法中,调用外部类的 AutoConfigurationPackages 的 register 方法,其中传参为:new PackageImport(metadata).getPackageName(),而实例化PackageImport的有参构造方法:
可看到是通过metadata的类名来获取所在的包名,所以需要明确下metadata是什么?怎么获取的?为什么通过这个就可以获取到对应根包路径?
4.2.1.metadata是什么及获取方式?
这个是官方提供的registerBeanDefinitions方法的释义,重点就在:
@param importingClassMetadata annotation metadata of the importing class,即:传参是导入类的原信息,实际就是被@Import标注的class信息,实际就是我们每个SpringBoot启动类的类信息【这里我们能知道,他通过Register类重写的registerBeanDefinitions方法获取被@Import标注的类信息,即SpringBoot启动类的类信息,而启动类我们都是放在根包下面的,所以大概知道个端倪了】
4.2.2.metadata能做什么?
拿到了metadata这个形参,具体做什么就是这个方法要做的了,所以我们再回头看下这个4.1.1中的register方法。

publtcstaticvodregistangiying

packageNames)

i((

(regtstry.containsbeanDefinition(BEAN))

BEANDERINtIoNBEAMDEINNREIStYGEBeADeFnitionEAN;

OSTUCTORATUERVALUESOMSNUCTORATGLEDSBERETRTION.GELCOSTUCTORAYUMGOTVALUE

IStTUtoARGGmdmULU.cuog

Felset

wGenericBeanDefinition;

GenericBeanDefinitionbeanbefinitionw

beanbefinition.setBeanclass(BasePackages.class;

beemDeftnttion.getconstutoArguentvalue.)

BEANDEFINiTIONSEROLEBEANDEFinitIROLEINFRASTRUCTURE);

registry.registerBeanDefinition(BEAN,eaefinitin;


大致思路是:首先会判断当前IOC容器中,是否已经有这个AutoConfigurationPackages,其中的BEAN是这个类的静态变量:private static final String BEAN = AutoConfigurationPackages.class.getName();
如果已经有了,则将其添加到basePackage【这个我们前面也有提到,实际就是一个去重之后是String数组,存储根包及所有子包组件,包含系统默认组件+用户自定义组件】中
如果没有,会创建一个新的Bean【存放在一个ConcurrentHashMap中维护,初始化size=256】,在else逻辑第三行会发现调用了一样方法:addIndexedArgumentValue,不同之处在于这里的第二个参数是直接传入的packageNames,即直接将主启动类的包名添加到basePackage中.即该注解还会帮我们完成Bean的注册与缓存。
4.2.3.问题:basePackages去重?为什么if-else两套?

【面试题】:register方法能获取所有的basePackage你刚讲到了,但是他怎么做到去重的呢?为什么这里需要有if-else两套逻辑,而且两套逻辑里的packageNames一个是直接添加,一个是调用方法呢?
【个人理解】:去重就是借助于一个Set<String>做到的,如下源码:
之所以就if-else两套逻辑,也是和Spring的Bean的IOC工厂一样,Bean是有缓存的,Bean的创建是单例+缓存进行存储的,底层是借助于一个size=256的ConcurrentHashMap【可能会问你Map体系了,顺便转移话题深度】进行存储,可以规避一些性能损耗,也可以快速响应,第一次那就先创建再添加,第一次创建的肯定没有添加到basePackage中,之后可能就已经添加过了,就需要进行去重了。一句带过就是:首次创建的Bean不会存在packageNames重复问题,而已存在的Bean可能已经添加过,需要借助于Set<String>进行去重,保证最后的basePackages都是唯一的。
4.2.4.小结
结合以上,我们能知道SpringBoot的自动配置,重要的一环就是获取全部的basePackage,而获取的方式是借助于@AutoConfigurationPackage 注解所引入的AutoConfigurationPackages.Register,对应的就是AutoConfigurationPackages下面的Register方法,该方法重写的registerBeanDefinitions方法帮我们获取全部的basePackages,同时帮我们做Bean注入,缓存,packageNames去重处理,以保证获取的name均为唯一。
4.3 AutoConfigurationImportSelector[核心]

注意每一层调用关系不要混乱,4.1-4.2平级,4.1.1是4.1的调用,4.1主要作用是获取basePackage,4.1.1是它的实现细节。

@Import(AutoConfigurationImportSelector.class)

@Import(AutoConfigurationPackages.Registrar.class)

@AutoConfigurationPackage

EnableAutoConfiguration

下面是AutoConfigurationImportSelector的继承关系视图,可以看到他继承了一系列的Aware接口,这也就保证了Bean在被初始化之后,能够获取对应的Aware资源【Aware系列在Spring的Bean声明周期中有强烈存在感,不是很清楚的可以百度下】

Importselector

Aware

Deferredimportselector

BeanClassLoaderAware

EnvironmentAware

BeanFactoryAware

Ordered

ResourceLoaderAware

AutoConfigurationImporSee

PCXAREdOyTFila5


4.3.1 @DeferredImportSelector
DeferredImportSelector继承自ImportSelector,DeferredImportSelector 的执行时机,是在 @Configuration 注解中的其他逻辑被处理完毕之后(包括对 @ImportResource、@Bean 这些注解的处理)再执行 ,即DeferredImportSelector 的执行时机比 ImportSelector 更晚。
4.3.2 实现原理[核心]

aOverride

LectImports(AnnotationMetadatannottinda)

publicstring门

(lisEnabled(annotationMletadata))

returnNO_IMPORTS;

MCGTtGOmztuomou.om.ooo

bidgrtordtoitmyagtouatmyumt

returnstringuttls.tostgonuntrygtonurn


【步骤1】:判断系统配置项是否开启了自动配置,也就是  isEnabled 方法,该方法默认true,未开启直接结束。
getProperty方法三个参数
第一个:当前环境变量配置的key,会通过这个key查找配置文件配置的value
第二个:返回类型,转义成Boolean
第三个:默认值true

【步骤2】:获取元数据,入参path:META-INF/spring-autoconfigure-metadata.properties
可以看到在三目运算符中,用户配置>系统配置,AutoConfigurationMetadata是借助于属性文件实现的内部类进行返回的。
【步骤3】:核心是加载自动配置类,上来还是判断是否开启了自动配置,没则直接结束
其中方法调用链路粗略绘制,如下所示:

ImportSelector

selectImport方法

步骤2:getCandidateConfigurations方法获取全部configurations

SpringFactoriesLoader.loadFactoryNames方法

getAutoConfigurationEntry

上述7步执行流程

13






关于SpringFactoriesLoader.loadFactoryNames方法,这里还是需要说明一下,关键就在于这个方法,帮我们实现的全局自动配置

PiVatesatictmlnChastomMtu

/这个文性开不思真有一个.iwsprtngBootajar有

PULUCStAic+nlStngFACOSSOUCEL

PIASTAtcLSLACooy

StringfactorycLassName-factorycLageNm

returiosdsprtmactortescast

@NultableclassLoader

LoadSpringFactortes

cLassLoader)

privatestaticMapstring,listastring->

棉无姓不在,医存有白安包

MultiVatueMapstring

iF(resuttlanul1)

returnresult;

]

try

EnuMerationURLurLs-(ClassLoaderl-nulL?

CLASSLOADERGETRESOURCES(FACTORIESRESOURCELOCATION

CLASSLOADERGESYSTEMRESOURCEFACTORIESRESOURCELOCATION));

result-newLinkedMultivalueMap*(;

while(urls.hasMoreElementsO)

全司:3prig.actoteorgmo.

URLurl-urls.nextelement;

UrlResourceresouRcenevUrLResource(UrL;

Proprtiesproertiesoettesui

Tor(MaP.EntrycEsentry:properties.entryset))t

G品ayEHSRYystrgentygeaue

result.add(factoryctassName,factoryName;

1在入级在

cache.put(classLoader,result);

returnFesult:

catch(IOExceptionex)

thrownewittegaLArgumentxcepttonuleooorieromoaton

N+O"ExJ;

FACTORIESRESOURCELOCATION


所以自动装配最后还是会回到配置文件,基于配置文件spring.factories的:   org.springframework.boot.autoconfigure.EnableAutoConfiguration=\,去加载自动配置类的全限定类名,这个结果会是一个很长的字符串,如下:

Demosb

Sotstringoxcluionthigxuon(u

69

RpFpNkR

resources

this.checkExcludedclasses.(configurtions

configurations.removea1i(exclusions);

static

configurstionsthisffiter(confzgurationutnurtt

autoCor

templates

thirututm

application.prope

returnStringutistosrft

test

DemosbApplicatlon

Debug

王业珂I

Debugger

Console

Vanables

attributesAnnotationAttributes@3055)size

configurationsArrayList@3578)size

0PNgtamwokbtu

1-"orgspringfamework.bootautoconigur.cach.uocnuio

2-orgspingiamewonkbootautocouoxcm

3-"orgsprngimewokbootautconigurcontexMesgeouAutocoio

4sPNMwUPrPuoomuo

5"rgspngTMwoBeu

6-"org.springframeworkbootautoconigurhttcode.codecAutoconigurtion

7-"gspringfameworkboot.autoconiguro.cutocoigui


之后装配到IOC容器中,之后的自动配置类就可以通过 ImportSelector 和 @Import 的机制被创建出,开始生效。
【SpringBoot自动装配结束】

4.3.3 自动装配做了什么
自动装配的最大好处,我觉得以下面这个例子说明应该就比较直观了。在传统的SSM框架中,我们使用Redis时候,需要在xml中定义Bean才可以使用,如:

XML

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<!-- redis template definition -->

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">

<property name="connectionFactory" ref="jedisConnectionFactory" />

<property name="keySerializer">

<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />

</property>

<property name="valueSerializer">

<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />

</property>

<property name="hashKeySerializer">

<bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />

</property>

<property name="hashValueSerializer">

<bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />

</property>

<!--开启事务  -->

<property name="enableTransactionSupport" value="true"></property>

</bean>

用的时候就这样声明式调用:

Java

运行代码复制代码

1

2

@Autowired

public RedisTemplate redisTemplate;

但是在SpringBoot框架中,我们引入jar包之后,只需要下面这样就可以直接使用,仔细看下你的SpringBoot项目是不是直接使用的,原因就在于自动化配置帮我们实现了。这应该就是最直观的感受了。

址址BHFuILEDP

NgLoeutecontgu234御LASEOUCEAMEIE

esprmgToctort2s

中于

PequghiParancroco

ReuSLAETETCOTOB

锈wekodonprop

TOUSOSHIINNG

mespietmort.bo.

WMeNE牛aWA

orB.springtrimwark.boouo

ore.sprietmtort.bo.i

ore.springtrmseork.boot.

NMSINSE-O0W66W5L06m61960320

orE.sprinetrenswork.bot.utoi

新NET出trd2.

org.springtrsmeuapk.boot.utoui

GMSENARPApcHeARSToncUrstortamewor.110

tre.pmeirmnort.bot.o.oui

R.sinetmo

HMSSNDRGLODTROTTEDTTO27A

MNIEEENMILEDTTEL927S

org.springtramswork.boot.utomiu.oiui

GMcaspwswteo.ctasohboomgbooooconoucom

orBspringtrwmwark.bootuou

GMEITL-NF

每m刚w通-phedba.dubmoningboolaucenfg

DEFENDENCIES

are.opringtrimtwark.oo.u.m

oe.springtrmwork.boot.uo.oui

orB.springtrimtwrk.boot.uoi

ore.pimetot.bo.oic.ii

ore.sprinetrmnsork.boot.utoofoi

orp.springtrumwork.boot.utcotiz.rreutdofgurtion

ore.springtrunsork.boot.utocontro.outccoticotion

org.springtranework.boot.utocontiurehz.nontootiurtion

东阳NEEATALAETALT9P2121

org.springtrimwork.oot.utconfiuttonfieuti

org.springtrameuork.boot.atoconfieure.hazLtHastAutoonfieurstion,

org.springtramsont.boot.aotizuat.airti

GMNKENONANACTENOLBOLOOOML39

ort.springtramcont.boot.cutofizue.httoeretontizuratio

ore.springtronesort.boot.utocoteure.httco.oeutontiurtion

GMAwENOrGApCTOROMEALAMBEDTOMTOMB.DOOABI

org.springirimork.boot.utocou..utaonuti

WMIEEEeuthaLaoel.lomokamt.ft9.033

orgspringtranework.oot.utocofo.ojinfoutaonfiguration

AMowTorgapleBdotwdiommbedbod903

hMIheeeaah-borts-borpe

orgspringtranework.boot.utocofuteitetfiui

长R乐生购店

tMwIwrrsodwprrodloepen343

ore.springtrumwork.boot.autoconfieure.jackon.ackonutdonfieuration,

hMNATEROPiERRLFOPL1D

org.springtrumework.boot.utoonfiue.uceutoonfizuration

HMSENOMAPECOPECU195

ce.springtrcsort.boot.utotrtoui

山MNELHENNTNPAETROEASLTAL9S

org.springfranswork.boot.utocofiu.ttotizui

市METONERSSSERTRCORE3132

ore.sprinetranssor.boot.uu

NMWEANLE661894

oe.springtrmsont.boot.auootriui


5.总结
@SpringBootApplication这个组合注解,主要分4个元注解+3个自定义注解:
@ComponentScan告诉去哪里扫描,如果遇到不想在启动初期加载进IOC容器的,主启动类组件通过TypeExcludeFilter,自动配置组件通过AutoConfigurationExcludeFilter进行过滤。
@SpringBootConfiguration标注主启动类,声明为一个配置类,为@EnableAutoConfiguration服务。
@EnableAutoConfiguration是自动化配置的核心,标识开启自动配置,是一个派生注解,其两个核心:@AutoConfigurationPackage帮助完成Bean注册,获取全部去重的packageNames;@AutoConfigurationImportSelector核心是借助于ImportSelector接口的selectImport方法实现,层层调用之后,最终会获取spring.factories文件下的配置信息,取到EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作。以前我们需要自己配置的东西,自动配置类都帮我们完成了。

相关文章
Day07
简介:本文讲解CAP与BASE理论核心要点,阐述分布式系统中一致性、可用性与分区容错性的权衡,解析Seata AT模式的执行流程,并探讨MQ消息防丢失、重复消费及积压处理等关键问题。
Day07
|
1天前
|
运维 Devops 开发工具
生产环境缺陷管理
针对大型团队多分支开发中bug管理难题,本文介绍基于go-git实现的分布式工具git-poison,通过“投毒-解药-银针”机制,实现bug的自动化追溯、发布卡点与影响范围精准识别,有效避免人为疏漏导致的生产事故,提升缺陷管理效率与系统稳定性。
生产环境缺陷管理
|
1天前
|
Dubbo Java 应用服务中间件
Day02
Day02:掌握Spring Cloud Gateway原理,基于Netty实现非阻塞请求转发;项目采用OpenFeign进行远程调用;深入JVM模型、垃圾回收、类加载及调优。
Day02
|
1天前
|
负载均衡 Dubbo 应用服务中间件
Day01
本文介绍微服务架构的适用场景及技术选型,对比单体与微服务优劣,详解Nacos与Eureka注册中心的心跳机制、服务治理差异,并涵盖常见负载均衡算法及SpringCloud Alibaba常用组件实践。
 Day01
|
1天前
|
存储 安全 算法
第一章 Java基础
本章系统讲解Java基础核心知识,涵盖重载与重写、==与equals、String三兄弟区别、异常体系、集合类原理(如HashMap结构与扩容)、线程并发(ThreadLocal、锁机制)、JVM内存模型、Lambda表达式、反射泛型及Tomcat优化等内容,深入浅出,助力夯实Java基础。
第一章 Java基础
|
1天前
|
存储 缓存 Java
自定义注解
本文介绍Java自定义注解的实现原理与应用,结合Spring AOP 和过滤器实现日志、权限控制及登录验证,涵盖注解定义、@Target、@Retention等核心语法,并通过代码示例展示实际使用流程。
 自定义注解
|
1天前
|
JSON 安全 Java
2.OAuth2.0实战案例
本文详细演示了OAuth2.0四种授权模式的实战应用,涵盖资源与授权服务搭建、配置及测试流程。通过具体案例展示授权码、简化、密码和客户端模式的实现步骤,并结合Spring Security完成认证授权,最终成功获取token并访问受保护资源。
|
1天前
|
存储 安全 前端开发
1.认识OAuth2.0
OAuth2.0是一种开放授权标准,允许第三方应用在用户授权下安全访问资源,无需获取用户账号密码。文中介绍了其四大授权模式:授权码模式(最安全,适用于Web应用)、简化模式(适用于前端单页应用)、密码模式(需高度信任)和客户端模式(服务间调用)。通过案例解析,说明OAuth2.0如何实现服务间资源共享与单点登录,提升系统安全性与用户体验。
1.认识OAuth2.0
|
1天前
|
存储 安全 前端开发
1.RememberMe简介及用法
RememberMe是一种保持用户登录状态的机制,通过Cookie实现关闭浏览器后仍可自动登录,避免重复认证。其原理是在用户首次登录并勾选“记住我”后,服务端生成Token并存储于Cookie,后续请求自动携带该Token进行校验,提升用户体验同时需注意安全风险。
|
1天前
|
前端开发 安全 Java
1.自定义认证前端页面
本文介绍如何在Spring Security项目中自定义认证前端页面,包括login.html的创建与配置、前后端代码整合及SecurityConfig安全配置详解,实现表单登录验证并完成启动测试。
 1.自定义认证前端页面