Spring Boot自动装配原理与自定义Starter实战

SIwave串扰分析保姆级教程:从Allegro文件导入到结果解读,手把手教你排查PCB信号问题 本文提供SIwave串扰分析的详细教程,从Allegro文件导入到结果解读,手把手教你排查PCB信号问题。涵盖环境准备、参数配置、串扰扫描技巧及实战案例,帮助工程师精准定位和解决高速PCB设计中的串扰问题,提升信号完整性分析能力。 阅读详情

1. 自动装配到底在解决什么问题

先聊一个最基础的痛点。做过传统 Spring 开发的朋友应该都有印象,早年间搭一个 SSM 工程,光是写配置就能耗掉大半天。 web.xml 、 spring-mvc.xml 、 spring-mybatis.xml 、数据源配置、事务管理器配置、扫描路径配置,一个文件漏了,启动直接报 BeanCreationException ,然后就是漫长的排查。

Spring Boot 出来以后,这些配置大部分消失了。你只需要引入一个 spring-boot-starter-web ,再写一个带 @SpringBootApplication 注解的启动类,一个能跑起来的 Web 项目就完成了。背后的功臣就是自动装配机制。

但很多人在面试或者实际工作中,对自动装配的理解停留在"加个注解就能用"的层面。一旦被问到" @SpringBootApplication 到底做了什么"" @EnableAutoConfiguration 是怎么加载那个自动配置类的""为什么自定义的 starter 能生效",就开始含糊了。

这篇文章把这些事情一次讲透,包括自动装配的核心原理、 AutoConfiguration.imports 文件的加载链路、 @Conditional 条件注解的生效逻辑,以及实际排查自动配置不生效的完整过程,最后再给出一个手写 starter 的案例。

2. 从三类核心注解拆解启动流程

2.1 @SpringBootApplication 是一个组合注解

先看 @SpringBootApplication 的源码定义:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
}

它由三个关键注解组合而成:

  • @SpringBootConfiguration :本质上是 @Configuration ,表明当前类是一个配置类。
  • @EnableAutoConfiguration :自动装配的入口注解,真正开启自动配置加载的逻辑就在这里面。
  • @ComponentScan :默认扫描启动类所在包及其子包下的组件。

需要注意一个容易踩坑的点: @ComponentScan 默认的扫描范围是启动类所在的包及子包。如果你把一些 @Service 、 @Repository 、 @Controller 放到包外面,除非显式指定 basePackages ,否则不会被扫描到。这也是很多项目启动后接口 404 的常见原因之一。

2.2 @EnableAutoConfiguration 的导入逻辑

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    Class<?>[] exclude() default {};
    String[] excludeName() default {};
}

关键点在于 @Import(AutoConfigurationImportSelector.class) 。 ImportSelector 接口有一个 selectImports(AnnotationMetadata metadata) 方法,Spring 在启动时会把返回的字符串数组中的类名都注册为 Bean 定义。 AutoConfigurationImportSelector 就是通过这个机制把候选的自动配置类批量引入。

2.3 AutoConfigurationImportSelector 做了什么

AutoConfigurationImportSelector 的 getCandidateConfigurations 方法负责加载候选配置类列表:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
            getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
    Assert.notEmpty(configurations,
            "No auto configuration classes found in META-INF/spring.factories. "
                    + "If you are using a packaging tool that does not support "
                    + "META-INF/spring.factories, consider using the "
                    + "new AutoConfiguration.imports files.");
    return configurations;
}

这里有一个版本差异需要特别注意:

  • Spring Boot 2.7 之前,自动配置类的名单写在 META-INF/spring.factories 文件里,key 是 org.springframework.boot.autoconfigure.EnableAutoConfiguration 。
  • Spring Boot 2.7 开始引入 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件, spring.factories 方式仍然兼容,但标记为废弃。
  • Spring Boot 3.0 之后,彻底移除了 spring.factories 方式,统一走 AutoConfiguration.imports 。

所以如果你在网上搜到老文章,照着写 spring.factories ,放在 Spring Boot 3.x 的项目里是不会生效的。这一点会在后面的排查章节详细演示。

3. 自动配置类是怎么被加载的

3.1 配置文件加载优先级

Spring Boot 2.7 之后,加载自动配置类的逻辑集中在 AutoConfigurationImportSelector 里的 getAutoConfigurationEntry 方法:

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. 获取候选配置类列表。
  2. 去重。
  3. 移除显式排除的类。
  4. 通过 ConfigurationClassFilter 做条件过滤,这一步会读取每个自动配置类上的 @ConditionalOnXxx 注解,判断是否满足条件。

3.2 条件注解在什么时候生效

自动配置类并不是无条件生效的。每个自动配置类上面都有一堆条件注解,比如:

  • @ConditionalOnClass :classpath 下存在指定类才生效。
  • @ConditionalOnMissingBean :容器中不存在指定 Bean 才生效。
  • @ConditionalOnProperty :配置文件中存在指定配置项且值匹配才生效。
  • @ConditionalOnWebApplication :当前是 Web 应用才生效。
  • @ConditionalOnExpression :SpEL 表达式结果为 true 才生效。

举例来说, DataSourceAutoConfiguration 上面有这些关键注解:

@AutoConfiguration(before = SqlInitializationAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({
        DataSourcePoolMetadataProvidersConfiguration.class,
        DataSourceCheckpointRestoreConfiguration.class
})
public class DataSourceAutoConfiguration {
}

意思是:只有当 classpath 下存在 javax.sql.DataSource 和 org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType 时,这个配置类才有资格参与后续判断,并且容器中不能存在 ConnectionFactory 类型的 Bean。

这种"按需加载"的设计让自动装配具备很强的灵活性。引入某个 starter 时,对应的自动配置类进入候选列表;但真正是否创建相关 Bean,还要看当前项目的依赖情况和用户配置。

3.3 自动配置类之间的顺序控制

自动配置类之间也存在依赖关系,例如 Redis 自动配置可能需要先初始化连接工厂,MyBatis 的自动配置需要依赖数据源的自动配置。Spring Boot 提供了两个注解来控制顺序:

  • @AutoConfiguration(after = XxxAutoConfiguration.class) :在指定的自动配置类之后执行。
  • @AutoConfiguration(before = XxxAutoConfiguration.class) :在指定的自动配置类之前执行。

注意,这个注解是 Spring Boot 2.7 之后引入的。更早的版本里控制顺序用的是 @AutoConfigureAfter 和 @AutoConfigureBefore 。如果项目升级到 2.7+,建议迁移到新注解上,因为老注解在某些场景下会失效。

4. 实战排查:自动配置为什么没生效

4.1 场景一:自定义 starter 在 Spring Boot 3.x 中不生效

之前有读者问过我一个问题:写了一个自定义 starter,把自动配置类配到了 spring.factories 里,在 Spring Boot 2.x 项目里一切正常,但换到 Spring Boot 3.2 之后,配置类一直没有被加载。

这个问题的根因很明确—— spring.factories 方式在 Spring Boot 3.0 里已经被移除了。Spring Boot 3.x 只认 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。

正确做法是在 src/main/resources/META-INF/spring/ 目录下新建文件,文件名必须是:

org.springframework.boot.autoconfigure.AutoConfiguration.imports

文件内容每行写一个自动配置类的全限定类名:

com.example.starter.config.MyAutoConfiguration

注意文件编码建议使用 UTF-8,不要写 BOM 头,否则解析时可能出问题。

4.2 场景二:加载了,但 Bean 没创建

配置文件配对了,自动配置类也进入了候选列表,但项目启动后需要用的 Bean 还是提示找不到。这种情况通常是条件注解不满足。

排查思路分三步走:

  1. 启动时打开自动配置报告。

在 application.yml 中配置:

debug: true

启动后日志中会输出 CONDITIONS EVALUATION REPORT ,里面会列出每个自动配置类的匹配状态: matched 或 not matched ,并且会说明不匹配的具体原因。

  1. 确认依赖是否齐全。

例如 RedisAutoConfiguration 要求 classpath 下存在 RedisOperations 类。如果你只是引入了 spring-boot-starter-data-redis 但没有引入对应的客户端库(比如 Lettuce 或 Jedis),条件注解就不会通过。

  1. 检查是否被用户自定义 Bean 拦截。

@ConditionalOnMissingBean 的意思是"容器中没有这个 Bean 时才生效"。如果你自己定义了一个同类型的 Bean,自动配置就会让位。这其实是 Spring Boot 留给使用者的扩展口子,但有时候也会造成困惑——明明依赖都齐了,自动配置就是不加载,查日志发现是 @ConditionalOnMissingBean 被用户自定义 Bean 挡住了。

5. 手写一个 Spring Boot Starter

单纯讲原理容易飘,实际动手写一个 starter 才能真正把自动装配逻辑串起来。下面以一个简单的验证码 starter 为例。

5.1 项目结构

新建一个 Maven 项目,项目名 captcha-spring-boot-starter ,整体结构如下:

captcha-spring-boot-starter
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── example
        │           └── captcha
        │               ├── CaptchaProperties.java
        │               ├── CaptchaService.java
        │               └── CaptchaAutoConfiguration.java
        └── resources
            └── META-INF
                └── spring
                    └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

5.2 引入必要依赖

pom.xml 中使用 Spring Boot 3.x 作为基础版本:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>3.2.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>3.2.0</version>
        <optional>true</optional>
    </dependency>
</dependencies>

spring-boot-autoconfigure 提供自动配置相关注解, spring-boot-configuration-processor 用于生成配置元数据,这样引用方在 IDE 里编写 application.yml 时能有配置提示。

5.3 定义配置属性类

@ConfigurationProperties(prefix = "example.captcha")
public class CaptchaProperties {

    /**
     * 验证码长度
     */
    private int length = 4;

    /**
     * 验证码有效期,单位秒
     */
    private int expireSeconds = 60;

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public int getExpireSeconds() {
        return expireSeconds;
    }

    public void setExpireSeconds(int expireSeconds) {
        this.expireSeconds = expireSeconds;
    }
}

这里通过 @ConfigurationProperties(prefix = "example.captcha") 把配置项绑定到属性字段上。引用方在配置文件中写 example.captcha.length=6 ,就会自动绑定到这个类的 length 字段。

5.4 定义业务服务类

public class CaptchaService {

    private final CaptchaProperties properties;

    public CaptchaService(CaptchaProperties properties) {
        this.properties = properties;
    }

    public String generateCode() {
        int length = properties.getLength();
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }
}

这个服务类不需要加任何 Spring 注解,因为它不是通过组件扫描注册的,而是由自动配置类显式创建的。

5.5 定义自动配置类

@AutoConfiguration
@EnableConfigurationProperties(CaptchaProperties.class)
@ConditionalOnClass(CaptchaService.class)
@ConditionalOnProperty(prefix = "example.captcha", name = "enabled", havingValue = "true", matchIfMissing = true)
public class CaptchaAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public CaptchaService captchaService(CaptchaProperties properties) {
        return new CaptchaService(properties);
    }
}

关键点解释:

  • @AutoConfiguration 是 Spring Boot 2.7 之后的标准写法,标记这是一个自动配置类。
  • @EnableConfigurationProperties(CaptchaProperties.class) 将配置属性类注册为 Bean,并开启属性绑定。
  • @ConditionalOnClass(CaptchaService.class) 确保 classpath 下有这个类才加载。如果在独立模块中,这个条件一定成立,这里只是为了演示写法。
  • @ConditionalOnProperty 让使用者可以通过 example.captcha.enabled=false 来关闭这个自动配置。
  • @ConditionalOnMissingBean 允许使用者自定义覆盖默认的 CaptchaService Bean。

5.6 注册自动配置类

在 resources/META-INF/spring/ 目录下创建 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,内容:

com.example.captcha.CaptchaAutoConfiguration

5.7 在业务项目中使用

创建一个普通的 Spring Boot 项目,引入这个 starter:

<dependency>
    <groupId>com.example</groupId>
    <artifactId>captcha-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

然后在任意一个 @Service 中注入 CaptchaService :

@Service
public class DemoService {

    private final CaptchaService captchaService;

    public DemoService(CaptchaService captchaService) {
        this.captchaService = captchaService;
    }

    public String getCaptcha() {
        return captchaService.generateCode();
    }
}

运行项目后, CaptchaService 会被自动注入,无需手动写任何 @Bean 方法。如果想要关闭自动装配,在 application.yml 中配置:

example:
  captcha:
    enabled: false

再次启动时, CaptchaAutoConfiguration 就会被条件注解拦截, CaptchaService 也不会注册,此时注入就会报错。这个开关机制在写公共组件时非常实用。

6. 自动装配的常见误区

6.1 误区一:自动装配等于全自动扫描

自动装配只在候选配置类的范围内生效,不负责扫描你项目里所有类。 @SpringBootApplication 中的 @ComponentScan 默认只扫描启动类所在包及子包,自动装配加载的是 AutoConfiguration.imports 里列出的配置类。两者是独立的路径,不要混为一谈。

6.2 误区二:引入了 starter 就一定生效

starter 引入后,自动配置类只是进入了候选名单,最终是否生效要看:

  • classpath 依赖是否满足条件。
  • 容器中是否已有用户自定义Bean。
  • application.yml 中的开关配置是否允许。

例如引入了 spring-boot-starter-data-redis ,但如果项目里没有 Redis 连接相关的客户端实现, RedisAutoConfiguration 也会跳过。

6.3 误区三: @ConditionalOnMissingBean 一定能兜底

@ConditionalOnMissingBean 的判断时机是在自动配置类生效时。如果你在别的配置类中,通过 @Bean 手动定义了同类型 Bean,且这个配置类先于自动配置类执行,那自动配置就会让位。如果顺序反过来,可能出现两个候选 Bean,启动时就会冲突。

6.4 误区四:配置类和普通 @Configuration 完全等价

自动配置类的加载时机和处理逻辑与普通 @Configuration 不同。自动配置类由 AutoConfigurationImportSelector 统一批量导入,并且在导入后会经过 ConfigurationClassFilter 过滤。普通 @Configuration 类则走常规的配置类解析流程。在自定义自动配置类时,不能假设它和普通配置类的执行时机完全相同。

7. 自动装配的加载链路速查

把整个加载链路完整梳理一遍:

  1. 启动类标注 @SpringBootApplication ,内部引入 @EnableAutoConfiguration 。
  2. @EnableAutoConfiguration 通过 @Import(AutoConfigurationImportSelector.class) 开启自动配置导入。
  3. AutoConfigurationImportSelector 调用 getAutoConfigurationEntry ,从 AutoConfiguration.imports 中读取候选配置类。
  4. 通过 removeDuplicates 去重,移除 exclude 指定的类。
  5. 通过 ConfigurationClassFilter 对每个候选类上的 @ConditionalOnXxx 注解进行条件判断。
  6. 通过 fireAutoConfigurationImportEvents 发布导入事件,允许监听器对导入结果做进一步处理。
  7. 通过 AutoConfigurationImportListener 或 AutoConfigurationImportEvent 可以自定义干预自动配置类的导入逻辑。

如果需要在项目中排查自动装配相关内容,重点关注 spring-boot-autoconfigure 包中的这几个类:

  • AutoConfigurationImportSelector :核心导入器。
  • AutoConfigurationImportEvent :导入事件。
  • AutoConfigurationImportListener :导入监听器。
  • AutoConfigurationSorter :排序器,处理自动配置类之间的先后关系。

8. 版本差异与升级建议

自动装配在 Spring Boot 3.x 中做了一些重要调整,主要集中在这几处:

  • spring.factories 方式被移除,统一使用 AutoConfiguration.imports 。
  • @AutoConfigureBefore 、 @AutoConfigureAfter 调整为 @AutoConfiguration(before = ...) 和 @AutoConfiguration(after = ...) 。
  • @AutoConfigurationPackage 注册的包名与启动类所在包保持一致,这个逻辑没有变化。
  • Jakarta EE 包名替换了 javax 命名空间,但在自动装配层面影响不大。

如果你正在把项目从 Spring Boot 2.x 升级到 3.x,建议按这个顺序处理:

  1. 全局搜索 spring.factories ,把所有自动配置类迁移到 AutoConfiguration.imports 。
  2. 全局搜索 @AutoConfigureBefore 和 @AutoConfigureAfter ,改成新注解写法。
  3. 用 debug: true 启动项目,查看自动配置报告,确认所有关键自动配置类处于 matched 状态。
  4. 重点核对数据源、Redis、MyBatis 等核心自动配置是否正常加载。

9. 实操心得

自动装配这块内容,光看源码很难形成完整画面。我建议在本地创建两个项目:一个是最小化的 Spring Boot 3.x 工程,另一个是自定义 starter。先在第一个项目里通过 debug: true 观察自动配置报告,找一个简单的自动配置类(比如 RedisAutoConfiguration )看它的条件注解和属性绑定;再动手把自定义 starter 跑通,把 AutoConfiguration.imports 文件、配置属性类、自动配置类的完整链路亲手验证一遍。

实际走完这两步之后,再回来看面试题就会顺很多。比如面试官问"Spring Boot 是如何实现自动装配的",你不需要背概念,直接按照" @EnableAutoConfiguration 引入 AutoConfigurationImportSelector ,从 AutoConfiguration.imports 读取候选类,通过条件注解过滤,最终注册为 Bean"这条链路讲,再补充一个自定义 starter 的实例,基本就能把问题答透。

最后说一个小技巧:排查自动配置不生效时,先开 debug: true 看条件评估报告,再检查依赖,最后确认用户自定义 Bean 是否干扰。按这个顺序来,九成问题都能在五分钟内定位。

《AgentScope-Java 深入浅出教程》第1章 AgentScope-Java 简介 AgentScope-Java 是一个面向智能体的编程框架,专门用于构建基于大语言模型(LLM)的 AI 应用程序。│ 你的业务应用 ││ AgentScope-Java 框架 ││ │ 智能体 │ │ 工具 │ │ 记忆 │ │ 模型 │ ││ LLM 服务 (DashScope/OpenAI/...) │能力说明类比ReAct 推理让智能体能够"思考"并"行动"就像人类思考后再做事工具调用让智能体能够执行外部操作就像人使用计算器、搜索引擎记忆管理让智能体能够记住对话历史。 阅读详情

相关推荐

用友U8库龄分析避坑指南:物料出入库日期计算的5个常见错误

本文深入剖析了在用友U8系统中进行库龄分析时,物料出入库日期计算的五个常见陷阱。从数据源选择、业务类型过滤、计价方式逻辑、期初数据处理到查询性能优化,逐一解析错误根源并提供避坑指南,帮助企业获得准确的库龄数据,有效管理库存与资金风险。

weixin_29209801的博客 450

Spring Boot 自动装配背后的 Condition:条件注解原理与自定义 Starter 实战

Spring Boot 最吸引人的能力之一,是自动装配:引入一个依赖后,组件便自动出现在容器中。这种能力并非魔法,而是由 Condition 条件判断机制驱动。Spring Framework 4.0 起提供 @Conditional 基础能力,Spring Boot 扩展为 @ConditionalOnClass、@ConditionalOnProperty 等语义化注解,在 BeanDefinition 注册前完成环境、类路径与配置的匹配,让框架能按需加载组件,既避免冲突,也降低资源浪费。对开发者而言,

weixin_29290863的博客 315

Hopf振荡器在机器人步态控制里到底怎么用?一个CPG仿生案例说清楚

本文深入解析了Hopf振荡器在机器人步态控制中的实际应用,通过CPG仿生案例详细展示了从数学方程到关节指令的完整流程。重点探讨了Hopf振荡器的极限环稳定性、参数调节技巧及自适应控制策略,为机器人运动控制提供了高效解决方案。

weixin_29284657的博客 190

Spring Boot自动装配原理与自定义starter实战拆解

自动装配是Spring Boot的核心理念,它通过条件注解和延迟导入机制,让开发者无须手工声明大量基础组件。理解AutoConfigurationImportSelector和条件装配原理,有助于排查启动日志中的Positive/Negative matches,以及解决Bean冲突问题。在工程实践中,自定义starter是沉淀通用能力的常用手段,从编写XxxAutoConfiguration和XxxProperties,到使用AutoConfiguration.imports注册,再到多版本兼容,都有规范

weixin_29238147的博客 277

基于ADS1299的8通道脑电采集系统硬件设计实战

生物电信号采集是医疗电子与可穿戴设备中的关键环节,微弱信号的高保真放大与数字化处理直接影响系统性能。高精度模数转换器与低噪声模拟前端设计成为工程实践的核心。ADS1299作为专用生物电测量芯片,集成多通道低噪声放大器与24位Δ-Σ ADC,广泛应用于脑电、心电等生理信号检测。本文基于ADS1299构建8通道脑电采集系统,详细阐述硬件架构、电源与参考设计、输入保护、PCB布局布线、固件SPI配置及数据读取,并结合实测数据分享噪声抑制与调试经验,为EEG采集设备开发提供完整参考。

weixin_29169505的博客 215

微信小程序地图开发避坑指南:腾讯地图API从配置到实战(附完整代码)

本文详细解析微信小程序中腾讯地图API的开发实践,从基础配置到高级功能实现,涵盖地图显示、地点搜索、路线规划等核心功能,并提供完整代码示例和常见问题解决方案,帮助开发者高效避坑。特别针对JavaScript SDK和map组件的使用进行了深度优化指导。

weixin_33725722的博客 483

Spring Boot自动装配原理与自定义Starter实战指南

Spring Boot自动装配是现代化Java开发的核心机制,其本质是通过约定优于配置原则解决传统Spring框架的复杂配置问题。从技术原理看,它基于Java SPI机制和@Conditional条件注解实现智能组件加载,通过分析类路径、Bean容器状态等运行时信息决定配置生效与否。这种机制大幅提升了开发效率,使得开发者只需关注业务逻辑而非基础设施配置。在微服务架构和云原生场景下,自动装配技术尤为重要,它支撑了Starter组件的即插即用特性。通过自定义Starter(如短信服务、分布式锁等),可以将通用能

weixin_33552698的博客 226

Unity3D实战:5分钟搞定RTSP监控视频播放(附完整代码)

本文提供了一套在Unity3D中快速集成RTSP监控视频播放的实战方案。通过采用LibVLCSharp for Unity这一成熟稳定的跨平台中间件,开发者可以轻松实现RTSP流的解码与渲染,并附有完整的C#代码示例,帮助用户在5分钟内完成集成,适用于智慧园区、安防监控等3D可视化场景。

weixin_29001655的博客 184

Spring Boot自动装配核心原理与自定义Starter实战

Spring Boot自动装配机制是Java企业级开发中的核心基础能力,它通过约定优于配置的方式替代传统XML繁琐装配,显著降低组件初始化成本。该机制借鉴Java SPI思想,结合条件注解进行动态判断,按需创建Bean并支持用户自定义覆盖。在微服务、基础组件封装等常见工程场景中,自动装配能有效减少配置地狱带来的维护负担,让开发者专注业务而非重复搭建框架。理解自动装配原理,掌握@Conditional、AutoConfiguration.imports及配置绑定等关键实现,是深入Spring Boot实战与高

weixin_26800111的博客 255

解锁RK1126与SC132GS摄像头适配密码:技术与代码全解析

本文详细介绍了瑞芯微RK1126芯片与SC132GS摄像头的适配方法。首先分析了RK1126的四核Cortex-A7处理器、Mali-T860 GPU等硬件特性,以及SC132GS的130万像素、全局快门等技术参数。重点阐述了基于MIPI CSI接口的硬件连接原理和基于V4L2框架的软件驱动设计,并提供了完整的初始化、数据采集和图像处理代码实现。针对常见连接和图像质量问题给出了解决方案,展现了该组合在智能安防、工业检测等领域的应用潜力,为开发者提供了实用的技术参考。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 1487

Nmap源码分析(端口扫描)

端口扫描是Nmap的核心功能,用于确定目标机的端口状态(开放、关闭、过滤等),也为Nmap的服务与版本扫描、OS扫描、脚本扫描提供基本的指引信息。所以,深入理解端口扫描的实现对分析其他的扫描方式很有帮助。 1简单回顾   首先简要回顾一下端口扫描的原理以及命令行选项。 1.1扫描原理   Nmap提供的10多种类型的端口扫描方法,如TCP SYN/ACK/FIN/Xmas/NULL/ Windows/Connect,FTP Bounce, Idle scan, UDP port u...

墨痕诉清风的博客 1591

Spring Boot自动装配原理与实战:从源码到自定义Starter

在Spring生态中,自动装配是Spring Boot最核心的特性之一,它让开发者无需手动编写大量配置即可快速构建应用。其原理基于@EnableAutoConfiguration导入AutoConfigurationImportSelector,从spring.factories或AutoConfiguration.imports中读取候选配置类,再通过@ConditionalOnClass、@ConditionalOnMissingBean等条件注解按需加载Bean,实现“约定优于配置”的动态协商机制。这

weixin_32612263的博客 86

高效内存管理与性能优化:Java Hotspot G1 GC全景解析

本文深入分析了 Java Hotspot G1 GC 的工作原理、特点以及优化策略。G1 GC 是一种为低延迟和高吞吐量设计的垃圾回收器,适用于大内存和高响应要求的应用。文章详细介绍了 G1 GC 的基本回收流程、各类垃圾回收策略,以及如何通过调优 JVM 参数来优化垃圾回收过程。通过监控工具和 GC 日志分析,开发者可以精准调整 G1 GC 的行为,提升应用的性能和响应速度。 参考文献、书籍及链接 1.https://tech.meituan.com/2016/09/23/g1.html 2.书

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 170万+

Spring Boot 自动装配深度解密:从原理到自定义 Starter 实战

本文深入解析了SpringBoot自动装配的核心原理与实现方式。主要内容包括: 自动装配概念:SpringBoot根据引入的依赖自动注册所需Bean到容器,遵循"约定大于配置"原则。 核心机制: 通过@EnableAutoConfiguration注解触发 SpringBoot3.x废弃spring.factories,改用AutoConfiguration.imports文件 条件注解(如@ConditionalOnClass)控制Bean注册条件

2401_88151415的博客 662

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Spring Boot 自动装配与 Starter 机制详解:从原理到自定义实战

Spring Boot 之所以能实现开箱即用,底层依赖的是一套基于条件注解与配置绑定的自动装配机制。其核心入口由 @EnableAutoConfiguration 触发,通过扫描 AutoConfiguration.imports 清单获取候选配置类,再结合 @ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty 等条件注解动态决定哪些配置生效,极大降低了依赖引入与配置维护的成本。理解这套决策链路,不仅是掌握框架启动原理的关键

weixin_34098209的博客 284

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【SpringBoot】Spring Boot Starter 详解与实战:手把手自定义 Starter

在传统 Spring 项目中,如果我们想使用Spring + MyBatis + Druid 连接池,通常需要手动添加多个依赖,并编写相关配置:</</</</</</</</然后还要写DataSource配置类、MyBatis 配置等。而的作用就是把这些繁琐的配置封装起来,让开发者只需要引入一个 Starter 依赖,即可自动装配所有组件。例如,使用只需这样:</</</无需手动配置DataSource,Spring Boot 会自动装配数据库相关的 Bean,大大减少了开发成本。

工一木子 2365

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Spring Boot自动装配原理深度解析:从@Conditional到自定义Starter实战

在Java企业级开发中,依赖注入和配置管理是构建可维护应用的核心基础。Spring框架通过IoC容器实现了依赖反转,而Spring Boot在此基础上引入了自动装配机制,将“约定大于配置”理念工程化。其技术原理基于条件化Bean加载,通过@Conditional系列注解(如@ConditionalOnClass、@ConditionalOnMissingBean)动态判断运行环境,实现智能配置。这一机制极大提升了开发效率,减少了冗余的XML或Java Config代码。在实际应用场景中,开发者可通过理解自动

weixin_28475533的博客 342

Spring Boot 自动装配原理与自定义 Starter 实战

Spring Boot 的自动装配是现代 Java 工程快速启动的关键机制。它通过 @EnableAutoConfiguration 与 AutoConfigurationImportSelector 从依赖中加载自动配置类,再结合 @ConditionalOnClass、@ConditionalOnMissingBean 等条件注解动态决定哪些 Bean 生效。这种“用户优先、配置兜底”的设计,让开发者只需引入依赖即可获得可用组件,同时保留按需覆盖和自定义扩展的能力。在实际工程中,无论是排查 RedisT

weixin_34094282的博客 209

Spring Boot自动装配:从原理到自定义Starter实战

配置管理是后端工程中绕不开的课题,传统XML与属性文件堆积常引发“配置地狱”。Spring Boot通过自动装配机制,利用条件注解与starter依赖,将样板配置收敛为默认推荐,开发者只需关注业务相关配置。其核心链路涉及@EnableAutoConfiguration、AutoConfiguration.imports与条件评估,理解这一原理能有效排查启动异常,并为自定义starter实现打下基础。无论是消解重复配置、统一团队通用能力,还是提升工程交付效率,自动装配都提供了优雅解法。本文从设计思路到源码机制

weixin_28738165的博客 268

自定义Spring Boot Starter实战:从自动装配原理到链路追踪组件开发

在Spring Boot生态中,约定优于配置的理念让开发者能快速构建应用,而自动装配机制正是这一切的基石。它通过扫描固定路径下的自动配置类,将第三方库和自定义组件无缝接入Spring容器。理解这一原理,不仅能解开框架启动的奥秘,更能在多模块、多服务的工程实践中实现公共能力的复用与解耦。日志链路追踪作为微服务排障的刚需场景,常依赖Filter与MDC协作生成traceId,若将其封装为自定义Starter,即可让业务方通过一行依赖快速获得全链路日志关联能力。本文以Spring Boot自定义Starter为切

weixin_29243063的博客 296

Spring Boot 自动装配原理详解(附自定义 Starter 实战)

Spring Boot 3.x 自动装配机制深度解析:本文从源码层面剖析了Spring Boot自动装配的核心原理。首先对比传统Spring配置的繁琐性,引出"约定优于配置"的设计理念;然后深入解析@SpringBootApplication注解的三层结构,重点分析@EnableAutoConfiguration的关键作用;最后通过AutoConfigurationImportSelector源码详细拆解自动配置的加载流程,包括候选配置获取、排除项处理和条件过滤等核心环节,并对比了2.x与3.x版本在配置加

weixin_65757664的博客 211

Spring Boot 自动装配原理与自定义 Starter 实战完全解析

在 Java 后端开发中,Spring Boot 的自动装配机制让开发者只需引入依赖即可获得开箱即用的组件,但其底层原理对很多人而言仍是黑盒。自动装配的本质是基于条件注解和导入机制,由框架在启动时根据类路径与环境智能注册 Bean,从而实现约定大于配置的工程实践。理解这一机制,不仅能帮助你排查 Bean 冲突、配置失效等常见问题,更能指导你设计高效、可扩展的自定义 Starter。本文从 Spring Boot 的 @EnableAutoConfiguration 与 AutoConfiguration.i

weixin_31528001的博客 253

Spring Boot自动装配原理与实战:从条件装配到自定义Starter

Spring Boot之所以能大幅简化企业级应用开发,核心在于其强大的自动装配机制。它改变了传统Spring中大量手工配置的痛苦,通过“约定优于配置”的理念,让开发者专注于业务逻辑。自动装配本质上是动态条件鉴权与Bean注册的集合,借助@ConditionalOnClass、@ConditionalOnMissingBean等条件注解,在应用启动时基于类路径、Bean状态和配置属性智能决定配置类的启用与否。理解这一原理,不仅能帮我们排查Bean注入失败、自动配置未生效等疑难问题,更是掌握Spring Boo

weixin_29209825的博客 200

Spring Boot自动装配原理与实战:从源码拆解到自定义Starter

在现代Java工程实践中,Spring Boot通过依赖注入与“约定优于配置”的理念,让开发者无需编写繁琐的XML或手动注册基础组件,就能快速拥有可运行的应用骨架。其核心能力来自一套自动装配机制:框架通过扫描约定的配置文件,结合@Conditional系列条件注解,在类路径、Bean定义、配置属性均满足条件时,自动创建所需的基础设施Bean。这一机制不仅解决了配置文件重复带来的低效问题,还以类似“精装房交付”的方式提供了高度弹性的扩展点——当用户自定义Bean时,自动装配会主动让位。从数据源到消息队列、从缓

weixin_33226548的博客 241

Spring Boot自动装配原理与实战:从源码剖析到自定义Starter

在Java企业级开发中,IoC容器与Bean管理是核心基础。Spring框架通过依赖注入实现对象解耦,但如何根据依赖自动创建并配置Bean曾长期依赖手工XML配置。Spring Boot的自动装配机制(AutoConfiguration)解决了这一痛点,它通过扫描classpath依赖、读取注册文件(如AutoConfiguration.imports),并结合条件注解如@ConditionalOnClass与@ConditionalOnMissingBean实现智能筛选,从而按需加载配置类。这一设计极大降

weixin_34005090的博客 206

Spring Boot自定义Starter实战:从自动装配原理到面试加分

Spring Boot的自动装配机制是框架的核心魅力所在,它让开发者只需引入依赖即可获得开箱即用的组件能力。理解这一机制,离不开条件注解的灵活运用,例如@ConditionalOnClass、@ConditionalOnMissingBean等,它们决定了配置类何时生效、Bean如何被覆盖。这种“约定优于配置”的设计哲学,使得公共能力可以被封装为独立组件,大大降低了多项目间的重复建设与维护成本。在实际工程中,无论是短信发送、消息队列还是分布式锁,都可以通过自定义Starter将初始化逻辑与配置细节收敛起来,

weixin_33290540的博客 217
上一篇: Java字符串替换:replace()与replaceAll()方法详解
下一篇: Web高精度反应时测试系统开发实践
金宇澄
博客等级 码龄8年 37粉丝 1万+原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值