首页 > 其他分享 >springboot2 自动装配原理

springboot2 自动装配原理

时间:2023-06-16 21:56:45浏览次数:53  
标签:装配 自动 扫描 ComponentScan annotationMetadata springboot2 注解 原理 configurations

springboot自动装配

Spring支持两种bean配置方式:XML配置、JavaConfig配置

@SpringBootApplication 注解

我们创建一个springboot项目后,一般要用该注解,然后在springbootApplication.run方法传入标注了该注解的类,这样就可以去加载spring的相关操作

@SpringBootApplication
public class SFastAdminApplication {
    public static void main(String[] args) {
        SpringApplication.run(SFastAdminApplication.class, args);
    }
}

内部结构

内部注释了三个注解:

@SpringBootConfiguration 配置类注解
@EnableAutoConfiguration 开启自动装配的注解
@ComponentScan进行包扫描,默认是扫描当前类所在的包下的所有组件

@SpringBootConfiguration(Spring 配置类,Bean)

该注解简单来说就是把当前类作为一个配置类,因为它内部就是一个@configuration注解,它也是一个@Component(组件)

它内部还有个@Indexed注解。

@Indexed注解

在应用中有大量使用@ComponentScan扫描的package包含的类越多的时候,Spring模式注解解析耗时就越长。因为需要通过反射扫描包嘛,然后一个一个遍历。

那么它在这里就体现出了优势,我们只需要在类或者接口(当然是有注解标注当前类或者接口是组件的)加上该注解即可提升启动性能

内部做了什么:

在项目中使用了@Indexed之后,编译打包的时候会在项目中自动生成META-INT/spring.components文件。
    当Spring应用上下文执行ComponentScan扫描时,META-INT/spring.components将会被CandidateComponentsIndexLoader 读取并加载,转换为CandidateComponentsIndex对象,这样的话@ComponentScan不在扫描指定的package,而是读取CandidateComponentsIndex对象,从而达到提升性能的目的。

@EnableAutoConfiguration(启用自动化装配, 重点)

该注解就是开启自动装配。

内部注释了三个注解:

@AutoConfigurationPackage自动配置包注解,扫描第三方的依赖注解

@Import(AutoConfigurationImportSelector.class)导入自动化配置类

@AutoConfigurationPackage(自动配置包)

@AutoConfigurationPackage是自动配置的提醒,是Spring Boot中的注解

该注解跟@ComponentScan一样,都是将Spring Boot启动类所在的包及其子包里面的组件扫描到IOC容器中。

但是区别是:

  • @AutoConfigurationPackage扫描@Enitity、@Mapper等第三方依赖的注解,

  • @ComponentScan只扫描@Controller/@Service/@Component/@Repository这些常见注解。

@Import(AutoConfigurationImportSelector.class)(导入自动化配置类)

AutoConfigurationImportSelector类实现了ImportSelector接口。

AutoConfigurationImportSelector有一个方法叫selectImports()就是我们到底要给容器中导哪些类。

然后所有的东西都是调用getAutoConfigurationEntry()方法得到的,然后再通过调用该方法得到的autoConfigurationEntry对象去获取Configurations集合,并且返回出去,最终交给容器。

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
        return NO_IMPORTS;
    }
    AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
    return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

getAutoConfigurationEntry(annotationMetadata):

该方法用于获取自动配置类的元数据。

注: 自动配置类是通过@Configuration和@Conditional注解来实现的。

protected AutoConfigurationEntry getAutoConfigurationEntry(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 = getConfigurationClassFilter().filter(configurations);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}

该方法代码解析:

  1. isEnabled(annotationMetadata)是判断是否启用自动装配,启用就继续,不起用则直接返回空的AutoConfigurationEntry

  2. getAttributes(annotationMetadata)是获取EnableAutoConfiguration注解的元数据,里面包含exclude(排除特定的自动配置类)和excludeName(排除特定的自动配置类名)

  3. getCandidateConfigurations(annotationMetadata, attributes);是获取自动装配配置类的,内部有SpringFactoriesLoader.loadFactoryNames获取,获取"META-INF/spring.factories"资源里的配置类。(注意的是,该文件是properties文件,我们在使用的时候全类名要写在org.springframework.boot.autoconfigure.EnableAutoConfiguration key名的后面)

  4. removeDuplicates(configurations);通过该方法去重,避免重复的全类名

  5. getExclusions(annotationMetadata, attributes);然后再对他们进行一个排除,排除条件就是通过getAttributes()方法获取的排除类或者类名

  6. checkExcludedClasses(configurations, exclusions);排除额外的类,不适合自动装配的类,若发现有这样的类则会抛出异常,让程序员处理。

  7. getConfigurationClassFilter().filter(configurations);过滤到不符合条件的类,只有符合条件的类才能在configurations里。

  8. fireAutoConfigurationImportEvents(configurations, exclusions);它通知所有监听器,自动装配的过程已经完成,并且告诉它们哪些AutoConfiguration类被应用了,哪些被排除了。

  9. 最终new AutoConfigurationEntry(configurations, exclusions);封装成AutoConfigurationEntry对象。

@ComponentScan(将指定路径上扫描)

@ComponentScan用于类或接口上主要是指定扫描路径,spring会把指定路径下带有指定注解的类自动装配到bean容器里。会被自动装配的注解包括@Controller@Service@Component@Repository等等。与ComponentScan注解相对应的XML配置就是<context:component-scan/>, 根据指定的配置自动扫描package,将符合条件的组件加入到IOC容器中;

该注解的常用属性:

  • basePackages和value:指定要扫描的路径(package),如果为空则以-@ComponentScan注解的类所在的包为基本的扫描路径。

  • basePackageClasses:指定具体扫描的类。

  • includeFilters:指定满足Filter条件的类。

  • excludeFilters:指定排除Filter条件的类。

  • useDefaultFilters=true/false:指定是否需要使用Spring默认的扫描规则:被@Component, @Repository, @Service, @Controller或者已经声明过@Component自定义注解标记的组件;

扩展

对本文里面提到的一些内容的补充。

@Import注解

import注解传入类可是单个类,也可指定多个类(数组形式)

三种用法:

  1. @Import一个普通类 spring会将该类加载到spring容器中

  2. @Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry的注册器,能手工往beanDefinitionMap中注册 beanDefinition

  3. @Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中

标签:装配,自动,扫描,ComponentScan,annotationMetadata,springboot2,注解,原理,configurations
From: https://www.cnblogs.com/liuscraft/p/17486580.html

相关文章

  • Java类加载原理中为何要设计双亲委派机制
    首先,给大家演示两个示例代码,我们自定义一个与Java核心类库中java.lang.String类名相同的代码:packagejava.lang;/***自定义java.lang.String类**@author编程老司机*@date2023-06-16*/publicclassString{static{System.out.println("加载自......
  • 基础知识-计算机组成原理
    (2023-6-16,未更新完)参考资料2021年计算机组成原理考研复习指导|王道考研【重学计算机】计算机组成原理|cnblogs|闪客sun概论可以在计算机中直接执行的语言和用助记符编写的语言是(机器语言)和(汇编语言)。机器语言是唯一可以直接执行的语言,汇编语言用助记符编写。而正则语言......
  • 学习笔记之Zookeeper内部原理解析
    1.1节点类型1.2Stat结构体(1)czxid-创建节点的事务zxid每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。(2)ctime-znode被创建的毫秒数(从19......
  • springboot2.4以后的配置
     (10条消息)springboot2.4以后的配置_spring.config.activate.on-profile_眉宇下的小格调的博客-CSDN博客......
  • k8s 集群原理
    1.背景Kubernetes作为容器应用的管理中心,对集群内部所有容器的生命周期进行管理,结合自身的健康检查及错误恢复机制,实现了集群内部应用层的高可用性。Kubernetes服务本身的稳定运行对集群管理至关重要,影响服务稳定的因素一般来说分为两种,一种是服务本身异常或者服务所在机器宕机,另......
  • springBoot 自动装配
    1.前言自动装配则是SpringBoot的核心,自动装配是如何实现的呢?为什么我们只要引入一个starter组件依赖就能实现自动装配呢,接下来就让我们一起来探讨下SpringBoot的自动装配机制2.自动装配原理提到自动装配,那么你首先得知道spring的SPI(serviceproviderinterface)机制,因为......
  • 代理ip匿名原理及那些行业需要代理ip
      互联网的高速发展,连带了代理ip也受到了更多人的使用,不同的行业都存在使用代理ip的情况,同时代理ip也以为匿名程度分成了高匿、普匿、透明代理,那么代理ip匿名的原理是什么呢?又有哪些行业需要代理ip呢?下面我们一起来分析一下。  一、代理ip匿名原理 代理IP匿名的原理基......
  • Spring----AOP入门介绍、原理与使用
    AOP介绍AOP:面向切面编程,无入侵式编程一种编程范式,指导开发者如何组织程序结构OOP:面向对象作用:在不惊动原始设计的基础上为其做功能增强概念定义Aspect(切面):描述通知与切入点的对应关系(执行位置和共性之间的关系)Aspect声明类似于Java中的类声明,在Aspect中会包含......
  • NodeJS系列(1)- 安装配置 NVM + NodeJS
    NodeJS(或Node.js) 是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。简而言之,NodeJS就是运行在服务端的JavaScript。NVM(NodeVersionManage),即NodeJS的版本管理工具。不同项目依赖不同的NodeJS版本......
  • Windows Server 2022 安装配置 MYSQL 及远程连接
    官方下载地址:https://dev.mysql.com/downloads/mysql/解压后新建my.ini放在解压目录下。配置环境变量:此电脑->属性->高级系统设置->环境变量->系统变量。找到path,新建D:\ProgramFiles\mysql-8.0.33-winx64\bin[mysqld]#设置3306端口port=3306#设置mysql的安装目录based......