- XML 配置:最传统、最基础的方式。
- Java 配置 (Annotation-Based):现代、主流的方式,推荐使用。
- 自动配置:Spring Boot 的核心,实现“约定优于配置”。
- 不同配置方式的对比与总结。
XML 配置 (传统方式)
在 Spring 早期和 Spring 3.x 时代,XML 是最主要的配置方式,所有的 Bean 定义、依赖注入(AOP、事务等)都在 XML 文件中完成。
核心文件
applicationContext.xml或beans.xml:这是 Spring 容器的核心配置文件。
- 引入 Schema (XSD):定义可以使用哪些 Spring 标签。
- 定义 Bean:使用
<bean>- 依赖注入:使用
<property>(setter 注入) 或<constructor-arg>(构造器注入)。- 自动扫描:使用
<context:component-scan>。- 引入属性文件:使用
<context:property-placeholder>。 - 依赖注入:使用
示例:applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1. 开启注解扫描,让 Spring 容器能找到 @Component, @Service 等注解的类 -->
<context:component-scan base-package="com.example.demo.service"/>
<!-- 2. 引入外部属性文件,例如数据库配置 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 3. 定义一个数据源 Bean (使用 Druid 连接池) -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 4. 定义一个 Service Bean (也可以通过 @Service 注解,这里用 XML 方式演示) -->
<bean id="userService" class="com.example.demo.service.UserServiceImpl">
<!-- 5. 依赖注入,将 dataSource 注入到 userService 中 -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
如何加载配置文件
// 在代码中手动获取 Spring 容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中获取 Bean
UserService userService = (UserService) context.getBean("userService");
userService.saveUser();
缺点:
- XML 配置冗长,当项目变大时,配置文件会变得非常臃肿。
- 配置和代码分离,维护困难,修改配置需要重新编译或重启应用。
- 类型安全差,很多错误只能在运行时才能发现。
Java 配置 (基于注解的方式)
从 Spring 3.x 开始,引入了 @Configuration 和 @Bean 等注解,使得配置可以完全用 Java 类来完成,这种方式更符合 Java 开发者的习惯,配置和代码在一起,类型安全,易于重构和 IDE 检查。
核心注解
@Configuration:标注在类上,表示这个类是一个 Spring 配置类,替代了 XML 文件。@Bean:标注在方法上,表示这个方法的返回值是一个 Bean,会注册到 Spring 容器中,方法名默认是 Bean 的 ID。@ComponentScan:替代<context:component-scan>,指定要扫描的包路径。@Import:导入其他配置类。@PropertySource:替代<context:property-placeholder>,指定属性文件的位置。
示例:SpringConfig.java
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import javax.sql.DataSource;
@Configuration // 1. 声明这是一个配置类
@ComponentScan("com.example.demo.service") // 2. 指定要扫描的包
@PropertySource("classpath:db.properties") // 3. 引入属性文件
public class SpringConfig {
// Spring 会自动注入 Environment 对象来读取属性
// private final Environment env;
// public SpringConfig(Environment env) {
// this.env = env;
// }
// 4. 定义一个数据源 Bean
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
// 5. 定义一个 Service Bean (通常通过 @Service 注解,这里用 @Bean 方式演示)
// UserServiceImpl 类上有 @Service("userService") 注解,这里就不需要再定义了。
// @Bean
// public UserService userService() {
// return new UserServiceImpl();
// }
}
如何加载配置类
// 使用 AnnotationConfigApplicationContext 来加载 Java 配置类 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 从容器中获取 Bean UserService userService = context.getBean(UserService.class); userService.saveUser();
优点:
- 配置与代码耦合,更易于理解和维护。
- 类型安全,IDE 可以提供智能提示和编译时检查。
- 支持重构,修改类名或方法名时,引用处会自动更新。
自动配置 (Spring Boot 方式)
Spring Boot 通过 自动配置 和 起步依赖 极大地简化了 Spring 应用的搭建和开发,它不是一种新的配置技术,而是对 Java 配置的增强和约定。
核心原理
@SpringBootApplication:这是一个复合注解,包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan。@EnableAutoConfiguration是自动配置的核心,它会根据类路径下的 jar 包和类,自动配置 Spring 应用上下文中需要的 Bean。
@Conditional:自动配置的核心逻辑,Spring Boot 提供了一系列@Conditional注解,@ConditionalOnClass:当类路径下存在某个类时才生效。@ConditionalOnMissingBean:当容器中不存在某个 Bean 时才生效。@ConditionalOnProperty:当配置文件中某个属性满足条件时才生效。
示例:application.properties / application.yml
在 Spring Boot 中,我们几乎不再需要手写 @Bean 来配置 DataSource、JdbcTemplate、RedisTemplate 等,Spring Boot 会根据我们引入的依赖(如 spring-boot-starter-jdbc)和配置文件自动完成。
application.properties
# 数据库配置 spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA 配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
application.yml (更推荐,结构更清晰)
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
如何自定义配置
如果自动配置的 Bean 不满足需求,我们可以通过以下方式覆盖:
- 自定义配置类:在
@Configuration类中定义自己的@Bean,Spring Boot 会优先使用用户定义的 Bean。 - 使用
@ConditionalOnMissingBean:在自动配置类中,如果用户已经定义了某个 Bean,自动配置就不会生效。 - 使用
@ConfigurationProperties:将配置文件中的属性绑定到一个 Java 对象中,实现类型安全的配置。
对比与总结
| 特性 | XML 配置 | Java 配置 | Spring Boot 自动配置 |
|---|---|---|---|
| 配置形式 | XML 文件 | Java 类 (@Configuration) |
注解 + 配置文件 (properties/yml) |
| 与代码关系 | 分离 | 耦合 | 耦合(配置)与分离(约定)结合 |
| 可读性 | XML 结构清晰,但冗长 | 面向对象,代码直观 | 高,通过属性名和值直接配置 |
| 维护性 | 差,修改需找文件 | 高,易于重构和 IDE 检查 | 极高,修改配置文件即可 |
| 类型安全 | 差,编译器无法检查 | 高,编译器检查 | 高,配置文件有提示 |
| 适用场景 | 遗留项目、需要严格分离配置与代码的项目 | Spring Framework 项目、Spring Boot 项目 | 现代 Spring Boot 项目的首选 |
| 核心思想 | 显式定义一切 | 用 Java 代码定义 Bean | 约定优于配置,按需自动 |
现代开发中的最佳实践
- 优先使用 Spring Boot:对于新项目,毫无疑问应该选择 Spring Boot,它能让你专注于业务逻辑,而不是繁琐的配置。
- 在 Spring Boot 中使用 Java 配置:虽然 Spring Boot 自动配置了大部分东西,但当你需要自定义一些复杂的、自动配置无法覆盖的 Bean 时,应该使用
@Configuration和@Bean的方式,配置一个多数据源、自定义拦截器等。 - 理解自动配置原理:不要把自动配置当成黑盒,学会查看 Spring Boot 的源码(特别是
spring-boot-autoconfigure包下的类),了解它是如何根据类路径和配置文件来决定创建哪些 Bean 的,这能帮助你快速定位和解决配置问题。 - 善用
application.yml:使用 YAML 格式的配置文件,它比.properties文件更结构化,层级关系更清晰,更适合复杂配置。
希望这份详细的梳理能帮助你彻底理解 Spring 的各种配置方式!
