Spring高频拓展

一、Spring 三种配置方式对比(XML / 注解 / JavaConfig)

1、三种配置方式介绍

  1. XML配置:早期Spring方式,将Bean全部写在xml文件中,解耦强、修改无需改代码。

  2. 注解配置:@Component、@Service、@Repository,自动扫描Bean,简单快捷。

  3. JavaConfig配置@Configuration + @Bean,纯Java代码配置,无XML,类型安全、编译检查。

2、优缺点对比 🔴

配置方式 优点 缺点 适用场景
XML 彻底解耦、修改不用改代码 繁琐、可读性差、无编译检查 老旧项目、第三方复杂Bean
注解 简洁、开发快、自动扫描 耦合代码、无法外部修改 业务层普通Bean(Service、Dao)
JavaConfig 类型安全、编译校验、优雅、无XML 少量代码量 第三方组件、自定义Bean、中间件配置

3、@Configuration 🟠

  • Full模式(默认):添加@Configuration,内部@Bean方法被拦截、单例、不会重复创建

  • Lite模式:不加@Configuration,只加@Component,内部@Bean每次调用都会new新对象。

Spring为@Configuration类生成CGLIB代理,拦截@Bean方法,保证容器中Bean唯一单例。


二、SpringBoot 自动配置原理(SPI + @EnableAutoConfiguration)

1、核心 🔴

加载SPI配置 → 读取自动配置类 → 条件注解按需注入Bean → 完成自动装配

2、详细流程

  1. @EnableAutoConfiguration:开启自动配置,底层导入 AutoConfigurationImportSelector

  2. SPI机制:读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件。

  3. 加载所有自动配置类(如WebMvcAutoConfiguration、DataSourceAutoConfiguration)。

  4. 条件注解生效:@ConditionalOnClass、@ConditionalOnMissingBean,判断类是否存在、Bean是否存在。

  5. 满足条件则自动创建Bean,注入Spring容器。

3、SPI机制作用

SPI:服务提供者接口,解耦配置与代码,SpringBoot利用SPI实现“第三方组件自动加载”,不用手动写Bean。


三、配置注入三大注解:@Value / @PropertySource / @ConfigurationProperties

1、三者区别 🟠

注解 作用 适用场景 优点
@Value 单个简单值注入 零散配置、少量字段 简单、灵活
@PropertySource 加载外部properties配置文件 自定义配置文件 分离配置、不写死代码
@ConfigurationProperties 批量绑定配置、前缀绑定 一组关联配置(数据库、线程池) 批量注入、类型安全、校验、优雅

2、写法示例(默写)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

// 1. @Value 单个注入
@Value("${user.name}")
private String name;

// 2. @PropertySource 加载外部配置
@Configuration
@PropertySource("classpath:custom.properties")

// 3. @ConfigurationProperties 批量绑定
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceConfig {
    private String url;
    private String username;
}
    

3、面试总结

  • 少量零散配置 → @Value

  • 自定义配置文件 → @PropertySource

  • 一组同类配置 → @ConfigurationProperties(推荐)


四、Spring 事件驱动模型(ApplicationEvent)

1、核心作用

解耦:发布事件、监听事件,实现业务解耦(观察者模式)。

2、三大核心组件

  1. ApplicationEvent:自定义事件(继承)。

  2. ApplicationListener:事件监听者,监听事件并处理。

  3. ApplicationEventPublisher:事件发布器,发布事件。

3、简单流程

业务代码 → 发布事件 → 监听者捕获 → 异步/同步处理业务

4、使用场景

  • 用户注册成功发送短信、邮件

  • 订单创建、订单完成、业务解耦

  • Spring内置事件:容器刷新、容器关闭


五、@Profile 多环境配置

1、作用

区分开发、测试、生产环境,不同环境加载不同Bean、不同配置

2、使用方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

// 仅dev环境生效
@Bean
@Profile("dev")
public User devUser(){ return new User(); }

// 仅prod环境生效
@Bean
@Profile("prod")
public User prodUser(){ return new User(); }

3、激活环境

  • 配置文件:spring.profiles.active=dev

  • 启动参数:–spring.profiles.active=prod


六、高频易错点汇总 🟠

1、@Autowired 和 @Resource 区别 🔴

对比 @Autowired @Resource
来源 Spring注解 JSR250 Java原生规范
默认规则 按类型byType 默认按名称byName
依赖required 默认必须注入,不可为空 可以为空
适用 Spring项目主流 通用性高、脱离Spring也能用

Autowired默认按类型注入,Resource默认按名称注入。

2、Bean 名称生成规则(极易错)

  1. 注解无指定name:首字母小写、类名作为Bean名称(UserService → userService)。

  2. 注解指定name:以指定名字为准。

  3. @Bean 默认名称:方法名作为Bean名称。

  4. 特殊规则:类前两位都大写,则Bean名称不变(ABCService→ABCService)。

3、事务传播行为易错场景(大坑) 🔴

易错1:REQUIRED(默认)

父子同一事务,只要一个异常,全部回滚

易错2:REQUIRES_NEW

新开独立事务,互不影响,外层回滚内层不回滚(日志必用)。

易错3:NESTED

嵌套事务,保存点机制,父回滚子必回滚,子回滚父可继续

易错4:内部调用事务一定失效

this.方法()不走代理,事务彻底失效。

易错5:异常捕获不抛出,事务不回滚

Spring默认只回滚RuntimeException,捕获不抛异常不会回滚。

易错6:非public方法事务失效

AOP动态代理无法拦截private/protected方法。