当前位置:首页 > 技术 > 正文内容

Spring Boot 核心机制解析:IoC、依赖注入、测试集成与配置绑定

访客 技术 2026年5月23日 3

一、JavaConfig 配置方式

传统 Spring 开发过度依赖 XML 描述,导致配置文件膨胀、维护困难。Spring 3.0 推出 JavaConfig 方案,允许用纯 Java 类替代 XML,但直到 Spring Boot 普及后才被广泛接受。JavaConfig 的核心优势在于:充分利用 Java 的面向对象特性(继承、多态)、彻底消除 XML、借助泛型实现类型安全的容器检索。

以下所有示例均基于 Maven 项目,首先引入基础依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>

1. XML 与 JavaConfig 的 IoC 对比

1.1 待管理的实体类

public class ProductService {
    private OrderService orderService;
    
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
    
    public ProductService() {
        System.out.println("ProductService 实例化");
    }
    
    public void startup() {
        System.out.println("ProductService 初始化完成");
    }
    
    public void cleanup() {
        System.out.println("ProductService 销毁");
    }
}

public class OrderService {
    public OrderService() {
        System.out.println("OrderService 实例化");
    }
}

1.2 XML 配置方式

<!-- spring-context.xml -->
<bean id="productService" class="demo.ProductService"/>
public class ContainerDemo {
    @Test
    public void xmlApproach() {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-context.xml");
        ProductService service = context.getBean(ProductService.class);
        System.out.println(service);
    }
}

1.3 JavaConfig 配置方式

关键注解说明:

  • @Configuration:标识该类为 Spring 配置类,等效于 XML 文件
  • @Bean:方法返回值纳入容器管理,等效于 <bean> 标签
  • AnnotationConfigApplicationContext:基于注解配置的容器实现
@Configuration
public class AppConfig {
    
    @Bean
    public ProductService productService() {
        return new ProductService();
    }
}
public class ContainerDemo {
    @Test
    public void javaConfigApproach() {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        ProductService service = context.getBean(ProductService.class);
        System.out.println(service);
    }
}

2. @Bean 高级属性配置

@Bean 注解支持多种属性,对应 XML 中的常用配置:

属性说明XML 对应
name指定别名name 属性
initMethod初始化回调init-method
destroyMethod销毁回调destroy-method

默认规则:方法名即为 bean 的标识符;作用域通过 @Scope("prototype") 调整,默认为单例。

3. 依赖注入的两种实现

3.1 参数注入法

@Bean
public ProductService productService(OrderService orderService) {
    ProductService service = new ProductService();
    service.setOrderService(orderService);
    return service;
}

3.2 方法调用法

@Bean
public ProductService productService() {
    ProductService service = new ProductService();
    service.setOrderService(orderService());
    return service;
}

原理:Spring 会拦截配置类中的实例方法,检查返回类型是否已存在于容器。若存在则直接复用,不存在才执行方法体创建新实例。

4. 注解驱动简化配置

当 bean 数量庞大时,@Bean 方法会导致配置类臃肿。可通过组件扫描 + 注解标记实现自动装配:

@Component
public class ProductService {
    private OrderService orderService;

    @Autowired
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
}

@Component
public class OrderService { }
@Configuration
@ComponentScan // 默认扫描当前包及子包
public class AppConfig { }

注意:第三方库的类无法添加 @Component,仍需在配置类中用 @Bean 声明,两种方式可共存。

二、Spring Test 与 JUnit 集成

引入测试依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.8.RELEASE</version>
    <scope>test</scope>
</dependency>
<dependency>
    >groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

1. JUnit 4 测试模式

// 基于 XML
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-context.xml")
public class SpringTestCase {
    @Autowired
    private ProductService productService;
    
    @Test
    public void test() {
        System.out.println(productService);
    }
}

// 基于配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class SpringTestCase {
    @Autowired
    private ProductService productService;
    
    @Test
    public void test() {
        System.out.println(productService);
    }
}

2. JUnit 5 测试模式

@SpringJUnitConfig(AppConfig.class)
class SpringTestCase {
    @Autowired
    private ProductService productService;
    
    @Test
    void test() {
        System.out.println(productService);
    }
}

3. 多配置类整合

// 从配置类
@Configuration
public class DataConfig { }

// 主配置类
@Configuration
@Import(DataConfig.class)
public class AppConfig { }

// 测试加载主配置即可
@SpringJUnitConfig(AppConfig.class)
public class SpringTestCase { }

若需引入遗留 XML 配置,使用 @ImportResource("classpath:legacy-context.xml")

三、Spring Boot 快速上手

1. 核心特性

Spring Boot 作为 Spring 生态的脚手架框架,设计目标是降低 Spring 应用的启动门槛。其标志性特点包括:内嵌 Servlet 容器(默认 Tomcat)、Starter 依赖机制、自动配置、独立 JAR 运行。

2. 项目构建

通过 Maven 手动搭建:

<packaging>jar</packaging>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
</parent>

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

启动类:

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

控制器:

@RestController
public class GreetingController {
    
    @GetMapping("/greet")
    public String greet() {
        return "Spring Boot 应用运行中";
    }
}

3. 关键机制解析

spring-boot-starter-parent:统一管理依赖版本,子模块声明时无需指定 version。其中 dependencyManagement 仅做版本声明,实际引入需子模块显式声明;dependencies 中的依赖则全局继承。

Starter 命名规范:官方 spring-boot-starter-*,第三方 *-spring-boot-starter,严禁使用 spring-boot 前缀。

打包插件:必须引入 spring-boot-maven-plugin 才能生成可执行 JAR,通过 java -jar 直接运行。

四、参数配置与绑定

1. 配置文件优先级

从高到低:

  1. 项目/config/application.properties
  2. 项目/application.properties
  3. classpath:config/application.properties
  4. classpath:application.properties

2. 属性绑定方式

2.1 @Value 逐个注入

@Component
public class DatabaseSettings {
    @Value("${db.driver}")
    private String driverClassName;
    @Value("${db.url}")
    private String jdbcUrl;
    @Value("${db.username}")
    private String user;
    @Value("${db.password}")
    private String password;
}

2.2 @ConfigurationProperties 批量绑定

@Component
@ConfigurationProperties(prefix = "db")
public class DatabaseSettings {
    private String driver;
    private String url;
    private String username;
    private String password;
    
    // getters and setters
}

若配置类使用 @Configuration 而非 @SpringBootApplication,需额外标注 @EnableConfigurationProperties 开启绑定支持。

2.3 Environment 编程式获取

@Configuration
@PropertySource("classpath:custom.properties")
public class AppConfig {
    @Autowired
    private Environment env;
    
    @Bean
    public DatabaseSettings databaseSettings() {
        DatabaseSettings settings = new DatabaseSettings();
        settings.setDriver(env.getProperty("db.driver"));
        settings.setUrl(env.getProperty("db.url"));
        settings.setUsername(env.getProperty("db.username"));
        settings.setPassword(env.getProperty("db.password"));
        return settings;
    }
}

优先级规则:application.properties 高于 @PropertySource 引入的自定义属性文件。

3. YAML 格式配置

db:
  driver: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://localhost:3306/demo
  username: root
  password: secret

相比 properties 的扁平结构,YAML 的层级缩进更适合表达复杂的配置关系。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。