springboot为什么要用延迟导入?

news/2024/10/11 2:30:56

Spring Boot使用了多种方式来实现自动配置,其中DeferredImportSelector接口是这些机制之一。

DeferredImportSelectorImportSelector的一个扩展,它允许延迟导入配置类直到所有@Configuration类都被处理完毕。这对于某些自动配置类需要在应用程序上下文的创建过程中的后期阶段才能做出决定的场景很有用。

为什么这么说呢?因为springboot导入的自动装配类大多都有@Conditional注解来判断这个装配类所依赖的类在当前路径下存不存在,@Conditional有很多种,有的只需要判断当前项目路径下有没有该类(比如:@ConditionalOnClass,有的需要判断当前spring容器中有没有该类的Bean比如:(@ConditionalOnBean)。

所以,当情况为后者时,使用@Conditional注解时必须确保我们导入的Bean已经存在了。所以就会延迟导入。那些加在启动类上的@EnableXXX注解就是这样的,在注解内部会用@Import导入一个标记类的Bean,然后再在自动装配类上@ConditionalOnBean注解判断有没有该Bean。这样就可以用@EnableXXX注解来控制是否导入自动装配类

下面我们分别举例:

举例1、

我举一个第一种情况的例子,假如我们项目中要用到Mybatis,那我们要导入mybatis的依赖和mybatis-spring-boot的依赖。当然,这两个依赖被springboot整合了

在mybatis-springboot的依赖中就会有一个自动装配类:MybatisAutoConfiguration

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class })
public class MybatisAutoConfiguration implements InitializingBean {

@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }) 的意思就是当类路径下存在SqlSessionFactorySqlSessionFactoryBean这两个类时,配置才会被激活,相应的Bean才会被创建。只要存在即可,不需要让他成为容器的Bean。因为这两个类都是mybatis包下的,我们总不能在这两个类上加一个@Component注解吧!所以只需要判断存在即可。所以只要我们导入了mybatis的依赖,这个判断就会生效。

举例2

这个例子就是我们自定义starter

新增一个标记类ConfigMarker

public class ConfigMarker{}

新增@EnableRegisterServer注解,利用@Import注解导入ConfigMarker到Bean容器

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({ConfigMarker.class}) //将ConfigMarker添加到容器中
public @interface EnableRegisterServer{}

改造HttpAutoConfiguration,新增条件注解@ConditionalOnBean(Marker.class)

@Configuration
@EnableConfigurationProperties(HttpProperties.class)
@ConditionalOnBean(Marker.class) //只有当Marker类的Bean在容器中存在时,当前自动配置类才会生效
public class HttpAutoConfiguration {@Resourceprivate HttpProperties properties; // 使用配置// 在Spring上下文中创建一个对象@Beanpublic HttpClient init() {HttpClient client = new HttpClient();String url = properties.getUrl();client.setUrl(url);return client;}}

测试一下,在另外一个springboot项目中导入当前工程starter,在主启动类上添加注解@EnableRegisterServer

大功告成。

如果不在主启动类上添加@EnableRegisterServer注解,当前的标注类Marker就不会被导入。就不会满足@ConditionalOnBean(Marker.class)注解的条件,HttpAutoConfiguration自动配置类也就不会被导入了。

这时候再使用:

 @Resourceprivate HttpClient httpClient;

程序就会报错,因为spring容器中根本就不存在这个这个Bean。

所以,就通过@EnableRegisterServer注解给自动装配提供了一个开关。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/27505.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

深入学习和理解Django视图层:处理请求与响应

title: 深入学习和理解Django视图层:处理请求与响应 date: 2024/5/4 17:47:55 updated: 2024/5/4 17:47:55 categories:后端开发tags:Django 请求处理 响应生成 模板渲染 表单处理 中间件 异常处理第一章:Django框架概述 1.1 什么是Django? Django是一个高级的Python Web框架…

常见的排序算法

常见的排序算法 目录一、冒泡排序(Bubble Sort)二、插入排序(Insert Sort)三、选择排序 (Selection Sort)四、希尔排序(Shell Sort)五、快速排序(Quick Sort)六、堆排序(Heap Sort)七、归并排序(Merge Sort)八、计数排序(Count Sort()九、桶排序 (Bucket Sort)十、基数排序…

K8S 创建Spring-boot项目并进行项目启动与访问

##Spring-boot 的helloworld 项目package com.example.demo;import java.time.LocalDateTime; import java.time.format.DateTimeFormatter;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; imp…

狂神spring学习笔记

1. Spring 1. 简介 一个融合器,一个简化开发的框架 spring官网 github地址 2. Maven坐标 <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency><groupId>org.springframework</groupId><artifactId>sp…

2024-05-04 如何为antd的table设置序号

给columns加多一列即可:const columns = [{title: "序号",key: "index",render: (_, record, index) => index + 1,},...]如图:

Multisim14--软件简介及安装教程(内含安装包)

安装包见文章末尾一、软件简介 Multisim是美国国家仪器(NI)有限公司推出的以Windows为基础的仿真工具,适用于板级的模拟/数字电路板的设计工作。它包含了电路原理图的图形输入、电路硬件描述语言输入方式,具有丰富的仿真分析能力。工程师们可以使用Multisim交互式地搭建电路…

随机抽奖

问题:随机抽奖公式 解决1:只一个抽奖结果=INDEX(A:A,RANDBETWEEN(2,11))解决2:多个抽奖结果且不能有重复=TAKE(SORTBY(A2:A11,RANDARRAY(10)),6)将抽奖名单按随机序排序,再提取前六个。

2024-05-04 如何去掉uniapp的h5开发中url存在的#号?

如果你正在用uniapp开发h5页面,你会发现h5页面的url里带有一个#号,比如:http://localhost:8080/#/pages/index/index 原因:uniapp默认模式导致 解决方案:修改uniapp默认模式为history,如下图所示: