springBoot自动注入原理的示例分析

springBoot自动注入原理的示例分析

这篇文章给大家分享的是有关springBoot自动注入原理的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

    @SpringBootApplication注解解读

    为什么我们的启动类上标注一个@SpringBootApplication注解,再加一个run()方法就可运行起来,可以看出我们的@SpringBootApplication注解是多么的强大。

    @SpringBootApplicationpublicclassApp{publicstaticvoidmain(String[]args){SpringApplication.run(App.class,args);}}

    @SpringBootApplication其实是由三个字注解来合成的。我们可以完全用这个三个注解来替换掉@SpringBootApplication。

    @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters={@ComponentScan.Filter(type=FilterType.CUSTOM,classes=TypeExcludeFilter.class),@ComponentScan.Filter(type=FilterType.CUSTOM,classes=AutoConfigurationExcludeFilter.class)})publicclassApp{publicstaticvoidmain(String[]args){SpringApplication.run(App.class,args);}}

    我们来说下这三个注解的一个作用,分别做了什么事情,为什么区区几个注解就可以让我们的程序跑起来。

    1.@SpringBootConfiguration

    其实点击进去就是一个 @Configuration,没什么特别的,学习过spring的朋友都知道,这是用于标注一个配置类的。

    2.@EnableAutoConfiguration

    重点就是在于@EnableAutoConfiguration 这个注解,我们先看下他的一个构成。

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

    @Inherited

    @Inherited : 如果标注此注解标识子类也可以进行继承,这个不太重要

    我们先来看.@EnableAutoConfiguration 注解中的@AutoConfigurationPackage注解里面的内容有什么 ? 可以看到导入了一个AutoConfigurationPackages.Registrar类型的组件

    @AutoConfigurationPackage

    @AutoConfigurationPackage:

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

    我们来看下导入的这个AutoConfigurationPackages.Registrar组件做了什么事情?

    registerBeanDefinitions? registerBeanDefinitions是不是就是往我们的容器中添加组件啊?那我们来看看他具体导入了那些组件。你可以将断点打在这两个方法上

    staticclassRegistrarimplementsImportBeanDefinitionRegistrar,DeterminableImports{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadatametadata,BeanDefinitionRegistryregistry){register(registry,newPackageImports(metadata).getPackageNames().toArray(newString[0]));}@OverridepublicSet<Object>determineImports(AnnotationMetadatametadata){returnCollections.singleton(newPackageImports(metadata));}}

    只要把BeanDefinition注册进去,往后我们只要调用getBean()就会得到该对象,当然不一定得我们自己调用,spring在底层最后刷新容器的时候,就会初始化所有的单实例bean,这也就是为什么我们直接使用相关注解就可以获取到该对象的原有。

    getBean()有两层意思:

    1.容器中有直接从缓存中获取

    2.容器中没有直接创建一个,也就是走bean的生命周期创建

    AutoConfigurationImportSelector.class

    @Import(AutoConfigurationImportSelector.class) 核心组件,我们来看看他做了什么事情。

    AutoConfigurationImportSelector他呢继承了DeferredImportSelector,DeferredImportSelector他呢有个内部接口Group,而Group中又有个方法process()
    所以我们来到AutoConfigurationImportSelector中的process()方法打上断点进行观察

    @Overridepublicvoidprocess(AnnotationMetadataannotationMetadata,DeferredImportSelectordeferredImportSelector){Assert.state(deferredImportSelectorinstanceofAutoConfigurationImportSelector,()->String.format("Only%simplementationsaresupported,got%s",AutoConfigurationImportSelector.class.getSimpleName(),deferredImportSelector.getClass().getName()));AutoConfigurationEntryautoConfigurationEntry=((AutoConfigurationImportSelector)deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);this.autoConfigurationEntries.add(autoConfigurationEntry);for(StringimportClassName:autoConfigurationEntry.getConfigurations()){this.entries.putIfAbsent(importClassName,annotationMetadata);}}

    这个方法一上来就要获取一些自动注入的条目autoConfigurationEntry,那我们看下他是怎么获取的,获取的究竟是什么东西?
    通过堆栈信息我们可以看到是通过invokeBeanDefinitionRegistryPostProcessors()这个方法调用过来的,说明在工厂初始化完毕,你可以往里面仍一些bean的定义信息了。

    进去就是这个方法

    protectedAutoConfigurationEntrygetAutoConfigurationEntry(AnnotationMetadataannotationMetadata){if(!isEnabled(annotationMetadata)){returnEMPTY_ENTRY;}AnnotationAttributesattributes=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);returnnewAutoConfigurationEntry(configurations,exclusions);}

    我们再进入这个方法

    在进入loadFactoryNames()方法中

    那我们去看看这个文件里面有什么

    结合上面的代码他是不是要加载org.springframework.boot.autoconfigure.EnableAutoConfiguration里面的内容,这些就是一些配置类的信息

    其实这个文件 spring.factories 里面的每一个类的权限的名称就是一个配置类,只不过springBoot把这些配置类都写好了,在我们某些场景需要的时候直接给你注入就行,这就说明了我们不用写那么多配置文件的原因。

    我随便点击一个类进去看看

    加载完成后: 怎么多?是不是全部第用得上啊?

    你看下面的代码,是不是要排除,移除掉,过滤掉一些啊,排除就是我们自己在注解中写的排除属性进行排除,让后就是经过一系列的筛选过滤。

    最后将这些信息put到entries中

    3.@ComponentScan

    @ComponentScan这个注解的功能就是扫描当前类上标注此注解所在包路径的所有类,这也就是为什么我们需要把主启动类放在最外面的原有,如果你想把配置类放在别的地方,那你就得自己手动指定包扫描路径.

    感谢各位的阅读!关于“springBoot自动注入原理的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

    发布于 2022-03-03 21:25:06
    收藏
    分享
    海报
    0 条评论
    40
    上一篇:C语言中结构体是什么 下一篇:Java中对象比较的示例分析
    目录

      0 条评论

      本站已关闭游客评论,请登录或者注册后再评论吧~

      忘记密码?

      图形验证码