Spring Boot Starter 与自动装配(Boot 3.0版本)

news2024/12/24 9:43:24

Spring Boot Starter 与自动装配

1、Starter

Starter可以理解为Spring Boot中的一站式集成启动器,它包含了一系列可以集成到应用中的依赖项(dependencies),可以快速一站式集成Spring组件及其他框架,而不需要到处找示例代码、依赖包及复杂的组件配置,我们只需要通过简单的参数配置就可以实现“开箱即用

一个完整的Spring Boot Starter一般需要包含以下组件:

  • 完成自动配置的自动配置模块

  • 为自动配置模块提供的所有依赖项

通过添加一个Starter可以轻松的将所需的功能快速的集成到应用中。比如,我们想使用Mybatis这款ORM框架访问数据库,只要加入官网提供的mybatis-spring-boot-starter启动器依赖即可:

<!-- MyBatis Spring Boot Starter -->  
    <dependency>  
        <groupId>org.mybatis.spring.boot</groupId>  
        <artifactId>mybatis-spring-boot-starter</artifactId>  
        <version>x.x.x</version>  
    </dependency> 

加入依赖后就能完成默认的自动配置并能直接使用。

2、自动配置

2.1、概述

Spring Boot Starter的核心原理就是自动配置,这也是整个Spring Boot框架的核心,开发者只需要按约定提供些许配置参数就能完成各种技术复杂组件的自动组装配置,这正是Spring Boot框架能迅速上手使用的原因。

Spring Boot官方所有的自动配置类都是由spring-boot-autoconfigure这个模块提供的,只要引入了对应组件的依赖,Spring Boot扫描到相关类时才会自动配置,没有引入是不会启用自动配置的。

2.2、命名规范

Spring Boot自动配置类一般以XxxAutoConfiguration命名,比如以下几个组件:

  • RabbitAutoConfiguration

  • FlywayAutoConfiguration

  • RedisAutoConfiguration

自动配置类需要注册到Spring Boot指定的自动配置文件中,低版本为类路径下的META-INF/spring.factories自动配置文件,Spring Boot 2.7对自动配置类的注册文件路径进行了变更,新的自动配置类注册文件路径如下

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.3、自动配置文件的加载原理

Spring Boot开启自动配置使用的是@EnableAutoConfiguration注解,一般使用组合了它的@SpringBootApplication主注解即可,@EnableAutoConfiguration注解的源码如下:

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

	/**
	 * Environment property that can be used to override when auto-configuration is
	 * enabled.
	 */
	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

	/**
	 * Exclude specific auto-configuration classes such that they will never be applied.
	 * @return the classes to exclude
	 */
	Class<?>[] exclude() default {};

	/**
	 * Exclude specific auto-configuration class names such that they will never be
	 * applied.
	 * @return the class names to exclude
	 * @since 1.3.0
	 */
	String[] excludeName() default {};

}

  • @AutoConfigurationPackage

    • 注册需要自动配置的包,如果不指定就是当前注解所在类的包
  • @Import

    • 导入配置类,这里导入的是AutoConfigurationImportSelector(实现类ImportSelector接口类)

如上所述,自动配置@Import注解导入的是AutoConfigurationImportSelector.class类,这也是这个注解的关键所在,它实现了ImportSelector接口:

public interface ImportSelector {

	/**
	 * Select and return the names of which class(es) should be imported based on
	 * the {@link AnnotationMetadata} of the importing @{@link Configuration} class.
	 * @return the class names, or an empty array if none
	 */
	String[] selectImports(AnnotationMetadata importingClassMetadata);

	/**
	 * Return a predicate for excluding classes from the import candidates, to be
	 * transitively applied to all classes found through this selector's imports.
	 * <p>If this predicate returns {@code true} for a given fully-qualified
	 * class name, said class will not be considered as an imported configuration
	 * class, bypassing class file loading as well as metadata introspection.
	 * @return the filter predicate for fully-qualified candidate class names
	 * of transitively imported configuration classes, or {@code null} if none
	 * @since 5.2.4
	 */
	@Nullable
	default Predicate<String> getExclusionFilter() {
		return null;
	}

}

这个注解有两个方法

  • selectImports(抽象方法)

    • 选择要导入配置类
  • getExclusionFilter(接口默认方法)

    • 用于返回要排除的类

AutoConfigurationImportSeletor类的selectImports方法的源码:

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

下面是isEnabled方法

这个函数的主要作用是判断当前是否启用了自动配置,如果当前类是AutoConfigurationImportSelector类,则根据属性值决定是否启用自动配置;否则,直接启用自动配置。

protected boolean isEnabled(AnnotationMetadata metadata) {
		if (getClass() == AutoConfigurationImportSelector.class) {
			return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
		}
		return true;
	}
  • 首先,它检查当前类是否等于AutoConfigurationImportSelector类。如果是,则通过getEnvironment().getProperty()方法获取一个属性值,该属性值用于覆盖自动配置的启用状态。如果该属性值为true,则返回true,表示自动配置已启用;如果该属性值为false或其他非true值,则返回false,表示自动配置未启用。

  • 如果当前类不等于AutoConfigurationImportSelector类,则直接返回true,表示自动配置已启用。

再根据getAutoConfigurationEntry方法进入getCandidateConfigurations方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // 导入候选自动配置列表	
   List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
			.getCandidates();
		Assert.notEmpty(configurations,
				"No auto configuration classes found in "
						+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

getCandidateConfigurations用于获取自动配置的类名列表。

  • 它通过加载AutoConfiguration类的候选者,并返回这些候选者的类名列表。

  • 如果候选者列表为空,则会抛出一个异常。

  • 这个方法主要用于Spring Boot的自动配置功能中,帮助Spring Boot在启动时自动加载相应的配置类,以实现快速开发。

2.4、自动配置原理

自动配置文件被加载后,就会注册里面提供的自动配置类了

例如:org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration

这是一个缓存的自动配置类

@AutoConfiguration(after = { CouchbaseDataAutoConfiguration.class, HazelcastAutoConfiguration.class,
		HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@Import({ CacheConfigurationImportSelector.class, CacheManagerEntityManagerFactoryDependsOnPostProcessor.class })
public class CacheAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public CacheManagerCustomizers cacheManagerCustomizers(ObjectProvider<CacheManagerCustomizer<?>> customizers) {
		return new CacheManagerCustomizers(customizers.orderedStream().toList());
	}

	@Bean
	public CacheManagerValidator cacheAutoConfigurationValidator(CacheProperties cacheProperties,
			ObjectProvider<CacheManager> cacheManager) {
		return new CacheManagerValidator(cacheProperties, cacheManager);
	}

	@ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class)
	@ConditionalOnBean(AbstractEntityManagerFactoryBean.class)
	static class CacheManagerEntityManagerFactoryDependsOnPostProcessor
			extends EntityManagerFactoryDependsOnPostProcessor {

		CacheManagerEntityManagerFactoryDependsOnPostProcessor() {
			super("cacheManager");
		}

	}

	/**
	 * Bean used to validate that a CacheManager exists and provide a more meaningful
	 * exception.
	 */
	static class CacheManagerValidator implements InitializingBean {

		....

	}

	/**
	 * {@link ImportSelector} to add {@link CacheType} configuration classes.
	 */
	static class CacheConfigurationImportSelector implements ImportSelector {

		@Override
		public String[] selectImports(AnnotationMetadata importingClassMetadata) {
			....
		}

	}

}
@AutoConfiguration

@AutoConfiguration注解指定了该类是一个自动配置类,并指定了它依赖的其他自动配置类

其源码如下:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore
@AutoConfigureAfter
public @interface AutoConfiguration {

	@AliasFor(annotation = Configuration.class)
	String value() default "";

	@AliasFor(annotation = AutoConfigureBefore.class, attribute = "value")
	Class<?>[] before() default {};

	@AliasFor(annotation = AutoConfigureBefore.class, attribute = "name")
	String[] beforeName() default {};

	@AliasFor(annotation = AutoConfigureAfter.class, attribute = "value")
	Class<?>[] after() default {};

	@AliasFor(annotation = AutoConfigureAfter.class, attribute = "name")
	String[] afterName() default {};

}

自动配置注解@AutoConfiguration组合了以下三个注解:

  • @Configuration(proxyBeanMethods = false)

    • 配置类注解,并不代理@Bean方法
  • @AutoConfigureBefore

    • 自动配置在XX配置之前
  • @AutoConfigureAfter

    • 自动配置在XX配置之后
@ConditionalOn*

在自动配置类中还有各种@ConditionalOn*的注解,这是一种条件注解,表示在满足指定条件时才会自动配置。

例如,在类CacheAutoConfiguration

  • @ConditionalOnClass(CacheManager.class)注解表示只有在类路径下存在CacheManager类时,该自动配置类才会生效

  • @ConditionalOnBean(CacheAspectSupport.class)注解表示只有当存在CacheAspectSupportBean时,该自动配置类才会生效

  • @ConditionalOnMissingBean(value = CacheManager.class, name = “cacheResolver”)注解表示只有在当前应用没有自定义的CacheManager Bean且没有名为cacheResolver的CacheManager Bean时,该自动配置类才会创建一个CacheManager Bean

2.5、邮件Starter

本节介绍spring-boot-starter-mail邮件启动器的集成与应用。

Spring 框架提供了一个发送邮件的抽象和实现:

  • import org.springframework.mail.javamail.JavaMailSender

  • import org.springframework.mail.javamail.JavaMailSenderImpl

MailSenderAutoConfiguration同样被注册在新的AutoConfiguration.imports自动配置文件中,该配置源码如下:

@AutoConfiguration
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
public class MailSenderAutoConfiguration {
	static class MailSenderCondition extends AnyNestedCondition {
		MailSenderCondition() {
			super(ConfigurationPhase.PARSE_CONFIGURATION);
		}
		@ConditionalOnProperty(prefix = "spring.mail", name = "host")
		static class HostProperty {
		}
		@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
		static class JndiNameProperty {
		}
	}
}
发邮件实践

首先创建一个spring-boot-mail工程,在Maven的pom.xml配置文件中加入

spring-boot-starter-mail邮件启动器依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
</dependencies>

然后在应用的application.properties配置文件中加入邮件自动配置参数:

spring:
  mail:
    host: smtp.exmail.qq.com
#    替换成自己的邮箱
    username: xxx@xxx.com
#    替换成自己的邮箱密码
    password: xxx
    properties:
      "[mail.smtp.socketFactory.class]": javax.net.ssl.SSLSocketFactory
      "[mail.smtp.socketFactory.fallback]": false
      "[mail.smtp.socketFactory.port]": 465
      "[mail.smtp.connectiontimeout]": 5000
      "[mail.smtp.timeout]": 3000
      "[mail.smtp.writetimeout]": 5000

mail:
#  替换成自己的邮箱
  from: xxx@xxx.com
  personal: PP
#  替换成自己的邮箱
  bcc: xxx@xxx.com
  subject: Spring Boot 发邮件测试主题

创建EmailController

/**
 * @author supanpan
 * @date 2024/03/11
 */
@Slf4j
@RequiredArgsConstructor
@RestController
public class EmailController {
    private final JavaMailSender javaMailSender;

    private final MailProperties mailProperties;


    @RequestMapping("/sendEmail")
    @ResponseBody
    public boolean sendEmail(@RequestParam("email") String email,
                             @RequestParam("text") String text) {
        try {
            MimeMessage msg = createMimeMsg(email, text, "java.png");
            javaMailSender.send(msg);
        } catch (Exception ex) {
            log.error("邮件发送失败:", ex);
            return false;
        }
        return true;
    }


    /**
     * 创建复杂邮件
     * @param email
     * @param text
     * @param attachmentClassPath
     * @return
     * @throws MessagingException
     * @throws UnsupportedEncodingException
     */
    private MimeMessage createMimeMsg(String email, String text, String attachmentClassPath) throws MessagingException, UnsupportedEncodingException {
        MimeMessage msg = javaMailSender.createMimeMessage();
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(msg, true);
        mimeMessageHelper.setFrom(mailProperties.getFrom(), mailProperties.getPersonal());
        mimeMessageHelper.setTo(email);
        mimeMessageHelper.setBcc(mailProperties.getBcc());
        mimeMessageHelper.setSubject(mailProperties.getSubject());
        mimeMessageHelper.setText(text);
        // 添加附件,java.png是在resources目录下的文件
        mimeMessageHelper.addAttachment("附件",
                new ClassPathResource(attachmentClassPath));
        return msg;
    }

    /**
     * 创建简单邮件
     * @param email
     * @param text
     * @return
     */
    private SimpleMailMessage createSimpleMsg(String email, String text) {
        SimpleMailMessage msg = new SimpleMailMessage();
        msg.setFrom(mailProperties.getFrom());
        msg.setTo(email);
        msg.setBcc(mailProperties.getBcc());
        msg.setSubject(mailProperties.getSubject());
        msg.setText(text);
        return msg;
    }
}

2.6、自定义Starter

本节实现一个简单的自定义Spring Boot Starter

2.6.1、创建Starter工程

根据Starter定义的规范,第三方的应用应该以*-spring-boot-starter的形式命名,所以接下来创建一个pp-spring-boot-starter的工程

2.6.2、创建自动配置类

创建一个简单的自动配置类:

@AutoConfiguration
@ConditionalOnProperty(prefix = "pp.starter", name = "enabled", havingValue = "true")
public class TestServiceAutoConfiguration {

    @Bean
    public TestService testService() {
        return new TestService();
    }

}

该配置类就是判断Spring环境配置中是否有pp.starter.enabled=true这个参数的值,如果有就配置一个TestService的Bean

public class TestService {

        public String getServiceName() {
            return "PP-Starter";
        }
}
2.6.3、注册自动配置类(spring.factories)

在Spring Boot 3.0应用的resource资源目录下创建imports自动配置文件:

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

添加要注册的自动配置类:

oi.pp.boot.starter.config.TestServiceAutoConfiguration

项目工程目录如下:

2.6.4、使用Starter

经过上述步骤,一个自定义的Starter就搭建好了,如果想使用这个自定义Starter,首先在本地打包,再新建另外一个应用并引用它进行测试。

创建一个pp-spring-boot-starter-sample,并添加自定义starter依赖:

    <dependencies>
        <dependency>
            <groupId>oi.pp.boot.starter</groupId>
            <artifactId>pp-spring-boot-starter</artifactId>
            <version>1.0</version>
            <scope>simple</scope>
        </dependency>
    </dependencies>

application.yml:

pp:
  starter:
   enabled: true

debug: true

# 排除指定的自动配置项
spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

创建启动器Application:


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

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

相关文章

CAP告诉你系统没法做到完美,只能做到权衡和适当

一、CAP介绍 CAP原理&#xff0c;全称为Consistency&#xff08;一致性&#xff09;、Availability&#xff08;可用性&#xff09;和Partition tolerance&#xff08;分区容错性&#xff09;&#xff0c;是分布式系统设计中的基本原理。它强调了在设计分布式系统时&#xff0c…

【深度学习笔记】优化算法——学习率调度器

学习率调度器 &#x1f3f7;sec_scheduler 到目前为止&#xff0c;我们主要关注如何更新权重向量的优化算法&#xff0c;而不是它们的更新速率。 然而&#xff0c;调整学习率通常与实际算法同样重要&#xff0c;有如下几方面需要考虑&#xff1a; 首先&#xff0c;学习率的大…

Verovio简介及在Windows10和Ubuntu 22.04上编译过程

Verovio是一个快速、便携、轻量级的开源库&#xff0c;用于将音乐编码倡议(Music Encoding Initiative(MEI))数字乐谱雕刻到SVG图像中。Verovio还包含即时转换器(on-the-fly converters)用于渲染Plaine & Easie Code、Humdrum、Musedata、MusicXML、EsAC和ABC数字乐谱。源代…

SSL证书:构建网络安全的基石

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C++容器适配器stack、queue、priority_queue

文章目录 C容器适配器stack、queue、priority_queue1、stack1.1、stack的介绍1.2、stack的使用1.3、stack的模拟实现 2、queue2.1、queue的介绍2.2、queue的使用2.3、queue的模拟实现 3、priority_queue3.1、priority_queue的介绍3.2、priority_queue的使用3.3、仿函数3.4、pri…

如何使用Everything+cpolar实现公网远程搜索下载内网储存文件资料

文章目录 前言1.软件安装完成后&#xff0c;打开Everything2.登录cpolar官网 设置空白数据隧道3.将空白数据隧道与本地Everything软件结合起来总结 前言 要搭建一个在线资料库&#xff0c;我们需要两个软件的支持&#xff0c;分别是cpolar&#xff08;用于搭建内网穿透数据隧道…

架构面试题汇总:mysql全解析(六)

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! MySQL面试题涵盖了索引优化、事务管理、并发控制以及存储格式等核心领域&#xff0c;旨在评估应聘者对数据库性能优化和数据一致性…

软件介绍-知网研学

知网研学 基本功能 功能特色&#xff1a; 1.高效检索和管理期刊论文、博硕士论文、会议论文、报纸、年鉴、网页内容等各类资源 2.已有题录与CNKI题录自动匹配&#xff0c;可一键更新&#xff0c;完善题录信息 3.阅读中可随手记录学习中的想法&#xff1b;对学科名词可随时查…

Dgraph 入门教程三《linux本地部署》

上一章中&#xff0c;我们用的官方的Clound操作的&#xff0c;怎么在本地部署一套Dgraph呢。这一章将做详细介绍。安装有好几种方式&#xff0c;最简单的就是联网部署。因为项目需要&#xff0c;这里先不介绍和测试线上部署了&#xff0c;只介绍离线部署。 1、下载安装包 Rel…

微信小程序仿QQ头像轮播效果

1、效果图 2、效果流程分析 1、第1个头像大小从1到0缩小的同时&#xff0c;第2个头像左移 2、上面动画结束后&#xff0c;延迟50ms&#xff0c;第3个头像从0到1放大 3、把头像列表顺序前移一位&#xff0c;并重置轮播状态&#xff0c;以此达到一个循环。然后继续第一个步骤 …

Stable Diffusion 详解

整体目标 文本生成图片&#xff1b;文本图片生成图片 网络结构 CLIP的文本编码器和图片生成器组成图像生成器&#xff0c;输入是噪声经过UNet得到图像特征&#xff0c;最后解码得到图像 前向扩散 模型直接预测图片难度比较大&#xff0c;所有让模型预测噪音然后输入-噪音…

Everything:文件查找工具,一搜即得

名人说&#xff1a;东边日出西边雨&#xff0c;道是无晴却有晴。——刘禹锡 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、软件介绍①Everything②核心功能③原理 二、下载安装①下载②安装 三、使用方法①文…

TRON Builder Tour 丹佛站活动获美联社等外媒高度评价

近日,波场TRON亮相ETH Denver大会并在期间成功举办TRON Builder Tour丹佛站活动,引发海外媒体热议。美联社、费加罗报、Cointelegraph等国际主流媒体及加密行业权威媒体均对此给予了高度评价,认为波场TRON在参会期间的表现及TRON Builder Tour活动的举办都展现了其坚定不移推动…

【大厂AI课学习笔记NO.74】人工智能产业技术架构

包括基础层、技术层和应用层。 人工智能的产业技术架构是一个多层次、多维度的复杂系统&#xff0c;它涵盖了从基础硬件和软件设施到高级算法和应用技术的全过程。这个架构通常可以分为三个主要层次&#xff1a;基础层、技术层和应用层。下面我将详细论述这三个层次及其细分内…

代码背后的女性:突破性别壁垒的技术先驱

个人主页&#xff1a;17_Kevin-CSDN博客 收录专栏&#xff1a;《程序人生》 引言 在计算机科学的历史长河中&#xff0c;有许多杰出的女性为这个领域的发展做出了重要贡献。她们不仅在技术上取得了卓越成就&#xff0c;还打破了性别壁垒&#xff0c;为后来的女性树立了榜样。今…

scrcpy远程投屏控制Android

下载 下载后解压压缩包scrcpy-win64-v2.4.zip scrcpy连接手机 1. 有线连接 - 手机开启开发者选项&#xff0c;并开启USB调试&#xff0c;连接电脑&#xff0c;华为手机示例解压scrcpy&#xff0c;在scrcpy目录下打开终端&#xff0c;&#xff08;或添加scrcpy路径为环境变…

【Web】浅聊Java反序列化之玩转Hessian反序列化的前置知识

目录 序列化 反序列化 Hessian1.0 Hessian2.0 Hessian反序列化核心&#xff1a;MapDeserializer#readMap的利用 总结 序列化 HessianOutput&Hessian2Output都是抽象类AbstractHessianOutput的实现类 HessianOutput#writeObject和Hessian2Output#writeObject的写法是…

Linux:kubernetes(k8s)Deployment的操作(12)

创建deployment 命令 kubectl create deploy nginx-deploy --imagenginx:1.7.9 再去使用以下命令分别查询 ubectl get deploy kubectl get replicaset kubectl get pod 他是一个层层嵌套的一个关系 首先是创建了一个 deploy 里面包含着replicaset replicaset里面含有…

文档版面分析数据集整理

版面分析数据集 这里整理了常用版面分析数据集&#xff0c;持续更新中&#xff1a; publaynet数据集CDLA数据集TableBank数据集D4LA 数据集DocLayNet文档布局分割数据集M6Doc数据集 版面分析数据集多为目标检测数据集&#xff0c;除了开源数据&#xff0c;用户还可使用合成工…

AIGC——ControlNet模型的原理

简介 ControlNet旨在控制预训练的大型扩散模型&#xff0c;以支持额外的输入条件。ControlNet能够以端到端的方式学习特定任务的条件&#xff0c;即使在训练数据集很小的情况下&#xff08;<50k&#xff09;&#xff0c;也能保持稳健性。此外&#xff0c;训练ControlNet的速…