springboot自动装配

2年前 (2022) 程序员胖胖胖虎阿
311 0 0

文章目录

    • 1、自动装配是什么及作用
    • 2、spring自动装配的原理
      • 2.1、启动类上注解的作用
        • @SpringBootApplication
          • @SpringBootConfiguration
          • @EnableAutoConfiguration
            • @AutoConfigurationPackage
            • @Import(AutoConfigurationImportSelector.class)
          • @ComponentScan
        • 2.2、springboot自动装配的流程
    • 3、相关注解的作用
      • @Conditional

1、自动装配是什么及作用

springboot的自动装配实际上就是为了从spring.factories文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给spring容器来帮我们进行管理

2、spring自动装配的原理

2.1、启动类上注解的作用

@SpringBootApplication

这个注解是springboot启动类上的一个注解,是一个组合注解,也就是由其他注解组合起来,它的主要作用就是标记说明这个类是springboot的主配置类,springboot应该运行这个类里面的main()方法来启动程序
springboot自动装配
这个注解主要由三个子注解组成:

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan
    springboot自动装配
@SpringBootConfiguration

这个注解包含了@Configuration,@Configuration里面又包含了一个@Component注解,也就是说,这个注解标注在哪个类上,就表示当前这个类是一个配置类,而配置类也是spring容器中的组件
springboot自动装配
springboot自动装配

@EnableAutoConfiguration

这个注解是开启自动配置的功能,里面包含了两个注解

  • @AutoConfigurationPackage
  • @Import(AutoConfigurationImportSelector.class)
    springboot自动装配
@AutoConfigurationPackage

这个注解的作用说白了就是将主配置类(@SpringBootApplication标注的类)所在包以及子包里面的所有组件扫描并加载到spring的容器中,这也就是为什么我们在利用springboot进行开发的时候,无论是Controller还是Service的路径都是与主配置类同级或者次级的原因
springboot自动装配

@Import(AutoConfigurationImportSelector.class)

上一个注解我们把所有组件都加载到了容器里面,这个注解就是将需要自动装配的类以全类名的方式返回,那是怎么找到哪些是需要自动装配的类呢?

1、AutoConfigurationImportSelector这个类里面有一个方法selectImports(),如下
springboot自动装配
2、在selectImport()方法里调用了一个getAutoConfigurationEntry()方法,这个方法里面又调用了一个getCandidateConfigurations()方法
springboot自动装配
3、在getCandidateConfigurations()方法里面调用了loadFactoryNames()方法
springboot自动装配
4、loadFactoryNames()方法里面又调用了一个loadSpringFactories()方法
springboot自动装配
5、关键就在这个loadSpringFactories()方法里面,在这个方法里,它会查找所有在META-INF路径下的spring.factories文件
springboot自动装配
springboot自动装配
6、在META-INF/spring.factories这个文件里面的数据是以键=值的方式存储,然后解析这些文件,找出以EnableAutoConfiguration为键的所有值,以列表的方式返回
springboot自动装配
springboot自动装配

@ComponentScan

这个注解的作用就是扫描当前包及子包的注解

2.2、springboot自动装配的流程

1、在springboot启动的时候会创建一个SpringApplication对象,在对象的构造方法里面会进行一些参数的初始化工作,最主要的是判断当前应用程序的类型以及设置初始化器以及监听器,并在这个过程中会加载整个应用程序的spring.factories文件,将文件中的内容放到缓存当中,方便后续获取;

2、SpringApplication对象创建完成之后会执行run()方法来完成整个应用程序的启动,启动的过程中有两个最主要的方法prepareContext()和refreshContext(),在这两个方法中完成了自动装配的核心功能,在run()方法里还执行了一些包括上下文对象的创建,打印banner图,异常报告期的准备等各个准备工作,方便后续进行调用;

3、在prepareContext()中主要完成的是对上下文对象的初始化操作,包括属性的设置,比如设置环境变量。在整个过程中有一个load()方法,它主要是完成一件事,那就是将启动类作为一个beanDefinition注册到registry,方便后续在进行BeanFactoryPostProcessor调用执行的时候,可以找到对应执行的主类,来完成对@SpringBootApplication、@EnableAutoConfiguration等注解的解析工作;

4、在refreshContext()方法中会进行整个容器的刷新过程,会调用spring中的refresh()方法,refresh()方法中有13个非常关键的方法,来完成整个应用程序的启动。而在自动装配过程中,会调用的关键的一个方法就是invokeBeanFactoryPostProcessors()方法,在这个方法中主要是对ConfigurationClassPostProcessor类的处理,这个类是BFPP(BeanFactoryPostProcessor)的子类,因为实现了BDRPP(BeanDefinitionRegistryPostProcessor)接口,在调用的时候会先调用BDRPP中的postProcessBeanDefinitionRegistry()方法,然后再调用BFPP中的postProcessBeanFactory()方法,在执行postProcessBeanDefinitionRegistry()方法的时候会解析处理各种的注解,包含@PropertySource、@ComponentScan、@Bean、@Import等注解,最主要的是对@Import注解的解析;

5、在解析@Import注解的时候,会有一个getImport()方法,从主类开始递归解析注解,把所有包含@Import的注解都解析到,然后在processImport()方法中对import的类进行分类,例如AutoConfigurationImportSelect归属于ImportSelect的子类,在后续的过程中会调用DeferredImportSelectorHandler类里面的process方法,来完成整个EnableAutoConfiguration的加载。

3、相关注解的作用

@Conditional

这个注解主要作用在类上,表示条件注入,就是当满足某个条件的时候,这个类才会被注入到 IOC 容器中,例如@ConditionalOnMissingBean,这个注解就是当容器中没有配置特定的Bean的时候,这个组件才会被注册到ioc容器中,否则会直接忽略

自动配置中使用的条件化注解 
===============================================================================================================
条件化注解 						    配置生效条件 
===============================================================================================================
@ConditionalOnBean 					配置了某个特定Bean 
@ConditionalOnMissingBean 			没有配置特定的Bean 
@ConditionalOnClass 				Classpath里有指定的类 
@ConditionalOnMissingClass 			Classpath里缺少指定的类 
@ConditionalOnExpression 			给定的Spring Expression LanguageSpEL)表达式计算结果为true 
@ConditionalOnJava 					Java的版本匹配特定值或者一个范围值 
@ConditionalOnJndi 					参数中给定的JNDI位置必须存在一个,如果没有给参数,则要有JNDI InitialContext 
@ConditionalOnProperty 				指定的配置属性要有一个明确的值 
@ConditionalOnResource 				Classpath里有指定的资源 
@ConditionalOnWebApplication 		这是一个Web应用程序 
@ConditionalOnNotWebApplication 	这不是一个Web应用程序 
===============================================================================================================

来自https://blog.csdn.net/musi_m/article/details/91893357

版权声明:程序员胖胖胖虎阿 发表于 2022年9月4日 上午12:40。
转载请注明:springboot自动装配 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...