Spring设计模式与依赖注入详解

作者:callNull日期:2026/1/14

📚 前言

这是我之前写 项目时的一些理解和感悟, 我喊了AI帮我润色了一下语言文字,发出来了,希望对大家有用
在学习Spring框架时,经常会遇到@Configuration@Bean@Service@Resource等注解,以及各种设计模式的应用。本文通过具体的代码示例(MailConfigMailService),深入浅出地解释这些概念,帮助理解Spring的核心机制。

🎯 核心问题

问题1:为什么需要@Configuration和@Bean?

问题2:为什么没有注解的类也能被@Resource注入?

问题3:构造函数参数与配置类的关系?

问题4:涉及了哪些设计模式?

让我们逐一解答这些问题。


🏭 第一部分:Spring容器 = 大仓库

🤔 没有Spring的痛苦

假设你要在3个地方发邮件:用户注册、密码重置、系统通知。

没有Spring配置的代码:

1// 第1个地方:用户注册
2public void register() {
3    // 每次都要写这一堆配置!
4    JavaMailSenderImpl sender = new JavaMailSenderImpl();
5    sender.setHost("smtp.qq.com");
6    sender.setPort(587);
7    sender.setUsername("myemail@qq.com");
8    sender.setPassword("mypassword");
9    
10    Properties props = new Properties();
11    props.put("mail.smtp.auth", "true");
12    props.put("mail.smtp.ssl.enable", "true");
13    props.put("mail.smtp.timeout", "5000");
14    props.put("mail.smtp.connectiontimeout", "5000");
15    props.put("mail.smtp.writetimeout", "5000");
16    sender.setJavaMailProperties(props);
17    
18    MailProperties mailProps = new MailProperties();
19    mailProps.setUsername("myemail@qq.com");
20    // ... 更多配置
21    
22    MailService mailService = new MailService(sender, mailProps);
23    mailService.sendRegisterCode("user@email.com", "123456");
24}
25
26// 第2个地方:密码重置
27public void resetPassword() {
28    // 又要写一遍同样的15行配置!!!
29    JavaMailSenderImpl sender = new JavaMailSenderImpl();
30    sender.setHost("smtp.qq.com");  // 重复!
31    sender.setPort(587);            // 重复!
32    sender.setUsername("myemail@qq.com");  // 重复!
33    // 又是15行重复配置...
34    
35    MailService mailService = new MailService(sender, mailProps);
36    mailService.sendResetEmail("user@email.com");
37}
38
39// 第3个地方:系统通知
40public void sendNotification() {
41    // 再写一遍同样的15行配置!!!
42    // 同样的重复代码...
43}
44

问题有多严重?

  1. 重复代码:同样的15行配置要写3次、5次、10次…
  2. 修改困难:如果邮箱密码变了,要改10个地方!
  3. 容易出错:某个地方配置写错了,邮件就发不出去
  4. 浪费时间:每次写业务代码都要先写配置

Spring的解决方案:仓库管理

Spring容器就像一个大仓库,统一管理所有对象。

1@Configuration  // "我是配置管理员"
2public class MailConfig {
3    
4    @Bean  // "我来准备现成的MailService放到仓库"
5    public MailService mailService(JavaMailSender sender, MailProperties props) {
6        // 复杂配置我来写,你不用管
7        return new MailService(sender, props);  // 现成的产品放入仓库
8    }
9    
10    @Bean  // "我来准备现成的JavaMailSender放到仓库"
11    public JavaMailSender javaMailSender() {
12        JavaMailSenderImpl sender = new JavaMailSenderImpl();
13        sender.setHost(env.getProperty("spring.mail.host"));
14        sender.setPort(Integer.parseInt(env.getProperty("spring.mail.port", "25")));
15        sender.setUsername(env.getProperty("spring.mail.username"));
16        sender.setPassword(env.getProperty("spring.mail.password"));
17        
18        Properties props = new Properties();
19        props.put("mail.smtp.auth", "true");
20        props.put("mail.smtp.ssl.enable", "true");
21        props.put("mail.smtp.timeout", "5000");
22        sender.setJavaMailProperties(props);
23        
24        return sender;  // 现成的邮件发送器放入仓库
25    }
26}
27

你的业务代码变得超简单:

1// 第1个地方:用户注册
2@Resource
3private MailService mailService;  // 从仓库提货
4
5public void register() {
6    mailService.sendRegisterCode("user@email.com", "123456");  // 一行搞定!
7}
8
9// 第2个地方:密码重置  
10@Resource
11private MailService mailService;  // 还是从仓库提货
12
13public void resetPassword() {
14    mailService.sendResetEmail("user@email.com");  // 一行搞定!
15}
16
17// 第3个地方:系统通知
18@Resource  
19private MailService mailService;  // 依然从仓库提货
20
21public void sendNotification() {
22    mailService.sendNotification("通知内容");  // 一行搞定!
23}
24

🏪 第二部分:Bean进入仓库的两种方式

📦 方式1:贴标签自动入库

1@Service  //  这就像给盒子贴了"请放入仓库"的标签
2public class UserService {
3    public void doSomething() {
4        // 业务逻辑
5    }
6}
7
8@Controller  //  另一种标签
9public class UserController {
10}
11
12@Repository  //  又一种标签
13public class UserRepository {
14}
15

工作流程:

1Spring启动  扫描所有类  发现@Service标签  自动创建UserService  放入仓库
2

🚚 方式2:手动搬运入库

1// MailService没贴标签,Spring不会自动放入
2public class MailService {
3    private final JavaMailSender javaMailSender;
4    private final MailProperties mailProperties;
5    
6    public MailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
7        this.javaMailSender = javaMailSender;
8        this.mailProperties = mailProperties;
9    }
10}
11
12@Configuration
13public class MailConfig {
14    @Bean  //  这里是"搬运工",手动把MailService放入仓库
15    public MailService mailService(JavaMailSender sender, MailProperties props) {
16        MailService service = new MailService(sender, props);  // 手动创建
17        return service;  // 手动放入仓库
18    }
19}
20

工作流程:

1Spring启动  发现MailConfig  看到@Bean方法  调用这个方法  得到MailService  放入仓库
2

🛍️ 从仓库取货

1@Resource  // "仓库管理员,给我一个MailService"
2private MailService mailService;  // Spring从仓库里拿给你
3
4// Spring不关心这个东西是怎么进仓库的(贴标签还是手动搬运)
5// 只要仓库里有,就能给你
6

关键理解:@Resource不看类有没有注解,只看仓库里有没有这个Bean!


🔗 第三部分:构造函数 = 需求清单

📋 MailService的需求清单

1public class MailService {
2    private final JavaMailSender javaMailSender;  // 需求1:我要一个邮件发送器
3    private final MailProperties mailProperties;  // 需求2:我要一个配置信息
4    
5    // 构造函数 = "需求清单"
6    public MailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
7        this.javaMailSender = javaMailSender;  // 收下需求1
8        this.mailProperties = mailProperties;  // 收下需求2
9    }
10    
11    public void sendRegisterCode(String to, String code) throws Exception {
12        // 使用构造函数收到的 javaMailSender 发邮件
13        MimeMessage message = javaMailSender.createMimeMessage();
14        
15        // 使用构造函数收到的 mailProperties 获取配置
16        MimeMessageHelper helper = new MimeMessageHelper(message, false);
17        helper.setFrom(mailProperties.getUsername());
18        helper.setTo(to);
19        helper.setSubject("注册验证码通知");
20        
21        String content = buildRegisterTemplate(code);
22        helper.setText(content, true);
23        
24        javaMailSender.send(message);  // 发送邮件
25    }
26}
27

🏭 MailConfig = 材料供应商

1@Configuration
2public class MailConfig {
3    
4    @Bean
5    public MailService mailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
6        //                           材料1: Spring自动提供    材料2: Spring自动提供
7        
8        // Spring调用这个方法时会自动传入这两个参数
9        return new MailService(javaMailSender, mailProperties);
10        //                      把材料1给MailService     把材料2给MailService
11    }
12}
13

🔄 完整的供需匹配过程

Step 1: MailService提出需求

1public MailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
2    // "要造我,必须给我这两样材料"
3}
4

Step 2: Spring准备材料

1// Spring自己准备或者其他地方准备好了:
2JavaMailSender sender = ...; // 材料1准备好(可能是自动配置或其他@Bean提供)
3MailProperties props = ...;  // 材料2准备好(可能是配置文件或其他@Bean提供)
4

Step 3: MailConfig组装

1@Bean
2public MailService mailService(JavaMailSender sender, MailProperties props) {
3    // Spring: "我把准备好的材料传给你"
4    // MailConfig: "好的,我用这些材料造MailService"
5    return new MailService(sender, props);  // 用材料造产品
6}
7

Step 4: MailService收到材料开始工作

1public void sendRegisterCode(String to, String code) {
2    // 使用构造函数收到的现成材料工作,不用自己创建
3    javaMailSender.send(message);
4}
5

🎯 如果没有构造函数参数会怎样?

错误做法:MailService自己找材料

1public class MailService {
2    public void sendRegisterCode(String to, String code) {
3        // 每次都要自己创建!很麻烦!很容易出错!
4        JavaMailSenderImpl sender = new JavaMailSenderImpl();
5        sender.setHost("smtp.qq.com");
6        sender.setPort(587);
7        sender.setUsername("myemail@qq.com");
8        sender.setPassword("mypassword");
9        // ... 15行重复配置代码
10        
11        sender.send(message);
12    }
13}
14

正确做法:通过构造函数接收现成的

1public class MailService {
2    private final JavaMailSender javaMailSender;  // 别人给我准备好的
3    
4    public MailService(JavaMailSender javaMailSender) {
5        this.javaMailSender = javaMailSender;  // 接收别人准备的
6    }
7    
8    public void sendRegisterCode(String to, String code) {
9        javaMailSender.send(message);  // 直接用,不用自己配置
10    }
11}
12

🎨 第四部分:涉及的设计模式

1. 🏭 工厂模式(Factory Pattern)

问题: 创建复杂对象很麻烦,到处都要重复写创建代码。

解决: 专门的工厂类负责创建对象。

1// MailConfig = 邮件服务工厂
2@Configuration
3public class MailConfig {
4    
5    @Bean  // 工厂方法:专门创建MailService
6    public MailService mailService(JavaMailSender sender, MailProperties props) {
7        // 复杂的创建逻辑集中在这里
8        return new MailService(sender, props);
9    }
10    
11    @Bean  // 工厂方法:专门创建JavaMailSender
12    public JavaMailSender javaMailSender() {
13        JavaMailSenderImpl sender = new JavaMailSenderImpl();
14        // 复杂的配置逻辑
15        sender.setHost(env.getProperty("spring.mail.host"));
16        sender.setPort(Integer.parseInt(env.getProperty("spring.mail.port")));
17        // ... 更多复杂配置
18        return sender;
19    }
20}
21

工厂模式的好处:

  • 创建逻辑集中管理
  • 业务代码不需要关心如何创建对象
  • 修改创建逻辑只需要改一个地方

2. 💉 依赖注入模式(Dependency Injection)

问题: 对象之间耦合度太高,A对象需要B对象时直接new B()。

解决: 外部注入依赖,而不是内部创建。

1// 错误做法:高耦合
2public class MailService {
3    public void sendMail() {
4        // 自己创建依赖,高耦合!
5        JavaMailSenderImpl sender = new JavaMailSenderImpl();
6        sender.setHost("smtp.gmail.com");  // 写死了配置
7        sender.send();
8    }
9}
10
11// 正确做法:依赖注入
12public class MailService {
13    private final JavaMailSender javaMailSender;  // 依赖
14    
15    // 构造器注入:外部传入依赖
16    public MailService(JavaMailSender javaMailSender) {
17        this.javaMailSender = javaMailSender;
18    }
19    
20    public void sendMail() {
21        javaMailSender.send();  // 使用注入的依赖,低耦合!
22    }
23}
24

依赖注入的好处:

  • 松耦合:MailService不关心JavaMailSender怎么创建
  • 可测试:容易替换为Mock对象进行测试
  • 灵活性:可以注入不同的实现

3. 🎯 策略模式(Strategy Pattern)

问题: 不同环境需要不同的配置策略。

解决: 根据条件选择不同的创建策略。

1@Configuration
2public class MailConfig {
3    
4    // 策略1:优先使用Spring Boot自动配置的JavaMailSender
5    @Bean
6    @ConditionalOnMissingBean(MailService.class)  // 条件:如果还没有MailService
7    public MailService mailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
8        return new MailService(javaMailSender, mailProperties);
9    }
10
11    // 策略2:如果没有JavaMailSender,自己创建一个
12    @Bean
13    @ConditionalOnMissingBean(JavaMailSender.class)  // 条件:如果还没有JavaMailSender
14    public JavaMailSender javaMailSender() {
15        // 从Environment读取Nacos配置,创建自定义的邮件发送器
16        JavaMailSenderImpl sender = new JavaMailSenderImpl();
17        sender.setHost(env.getProperty("spring.mail.host"));
18        // ... 从配置中心读取配置
19        return sender;
20    }
21}
22

策略模式的体现:

  • 本地application.yml有配置 → 使用策略1(Spring Boot自动配置)
  • 只有Nacos远程配置 → 使用策略2(手动创建)
  • 自动适配不同的部署环境

4. 🔌 适配器模式(Adapter Pattern)

问题: 配置来源(Environment)和目标对象(JavaMailSender)接口不匹配。

解决: 创建适配器转换接口。

1@Bean
2public JavaMailSender javaMailSender() {
3    JavaMailSenderImpl sender = new JavaMailSenderImpl();
4    
5    // 适配器:将Environment配置适配到JavaMailSender接口
6    sender.setHost(env.getProperty("spring.mail.host"));           // 适配host
7    sender.setPort(Integer.parseInt(env.getProperty("spring.mail.port", "25"))); // 适配port  
8    sender.setUsername(env.getProperty("spring.mail.username"));   // 适配username
9    sender.setPassword(env.getProperty("spring.mail.password"));   // 适配password
10    
11    // 适配Properties配置
12    Properties props = new Properties();
13    String timeout = env.getProperty("spring.mail.properties.mail.smtp.timeout", "5000");
14    props.put("mail.smtp.timeout", timeout);
15    sender.setJavaMailProperties(props);
16    
17    return sender;
18}
19

适配器模式的体现:

  • Environment = 被适配者(配置源)
  • javaMailSender()方法 = 适配器(转换逻辑)
  • JavaMailSender = 目标接口(期望的接口)

🔄 第五部分:完整工作流程

📋 项目启动时的Bean创建流程

11. Spring Boot启动
2   
32. 扫描AutoConfiguration.imports文件  
4   
53. 发现MailConfig配置类
6   
74. 处理@Bean方法:
8   - 检查:容器中有JavaMailSender吗?
9     *   直接使用
10     * 没有  调用javaMailSender()方法创建
11     
125. 处理@Bean方法:
13   - 检查:容器中有MailService吗?
14     *   跳过
15     * 没有  调用mailService()方法创建
16   
176. 将创建的Bean存储到Spring容器中
18   
197. 启动完成,Bean准备就绪
20

🛍️ 业务代码使用Bean的流程

1@Service
2public class UserService {
3    
4    @Resource  // 1. Spring看到@Resource注解
5    private MailService mailService;  // 2. 从容器中查找MailService
6                                     // 3. 找到后注入到这个字段
7    
8    public void registerUser(String email) {
9        // 4. 直接使用注入的MailService,一行搞定
10        mailService.sendRegisterCode(email, "123456");
11    }
12}
13

🎯 关键理解

  1. @Configuration + @Bean = 工厂 + 生产线
  2. 构造函数参数 = 需求清单
  3. Spring容器 = 仓库管理员
  4. @Resource = 取货单

核心好处:

  • 写一次配置,到处都能用
  • 业务代码简洁,专注业务逻辑
  • 修改配置只需要改一个地方
  • 自动处理依赖关系

🎓 第六部分:学习要点总结

Bean注册的两种方式

方式使用场景示例
类注解简单业务类,不需要复杂配置@Service UserService
@Bean方法需要复杂配置的对象MailService、DataSource

注解职责分工

注解作用位置职责
@Configuration标识配置类
@Bean方法标识Bean工厂方法
@Service/@Controller标识业务组件
@Resource/@Autowired字段/方法依赖注入

设计模式实际应用

  1. 工厂模式 → 统一创建复杂对象
  2. 依赖注入 → 降低耦合度
  3. 策略模式 → 环境自适应
  4. 适配器模式 → 接口兼容

核心记忆口诀

  • MailConfig = 服务员(提前准备好菜)
  • 构造函数 = 订餐单(我要什么)
  • Spring容器 = 仓库(统一管理)
  • @Resource = 取货(直接用现成的)

💡 第七部分:常见问题解答

Q1: 为什么MailService没有@Service注解也能用?

A1: 因为通过MailConfig的@Bean方法手动注册到了Spring容器。@Resource只看容器里有没有,不看类有没有注解。

Q2: 构造函数参数是干什么用的?

A2: 构造函数参数是"需求清单",告诉Spring"要创建我需要这些材料"。MailConfig负责准备材料并传递给构造函数。

Q3: 什么时候用@Service,什么时候用@Bean?

A3:

  • 简单业务类用@Service(让Spring自动管理)
  • 需要复杂配置的类用@Bean(手动控制创建过程)

Q4: @Configuration和@Bean必须配合使用吗?

A4: 是的。@Configuration标识配置类,@Bean标识具体的Bean工厂方法,缺一不可。


🚀 第八部分:扩展应用

📦 类似的配置示例

1// 阿里云短信配置
2@Configuration
3public class AliSmsConfig {
4    
5    @Bean("aliClient")
6    public Client client() {
7        Config config = new Config()
8            .setAccessKeyId(accessKeyId)
9            .setAccessKeySecret(accessKeySecret)
10            .setEndpoint(endpoint);
11        return new Client(config);  // 复杂对象创建
12    }
13}
14
15// 数据库配置  
16@Configuration
17public class DatabaseConfig {
18    
19    @Bean
20    public DataSource dataSource() {
21        HikariDataSource dataSource = new HikariDataSource();
22        dataSource.setJdbcUrl("jdbc:mysql://localhost/db");
23        dataSource.setUsername("user");
24        dataSource.setPassword("pass");
25        dataSource.setMaximumPoolSize(20);  // 复杂配置
26        return dataSource;
27    }
28}
29

🎯 最佳实践

  1. 配置类命名:以Config结尾,如MailConfig、DatabaseConfig
  2. Bean命名:使用@Bean(name=“xxx”)指定明确的名称
  3. 条件注解:使用@ConditionalOnMissingBean避免重复创建
  4. 配置分离:不同功能的配置放在不同的配置类中

📝 总结

通过MailConfig和MailService的例子,我们学习了:

  1. Spring容器的仓库管理机制
  2. Bean创建的两种方式(类注解 vs @Bean方法)
  3. 依赖注入的工作原理(构造函数参数的作用)
  4. 实际应用中的设计模式(工厂、依赖注入、策略、适配器)

核心思想: Spring帮我们做繁琐的对象创建和管理工作,我们专注于业务逻辑。这就是现代框架的价值 —— 让复杂的事情变简单,让重复的事情变自动

记住:设计模式不是为了炫技,而是为了解决实际问题。在Spring中,这些模式的应用让我们的代码更加优雅、可维护、可扩展。


📧 第九部分:配置文件的作用机制

🎯 邮箱配置在Spring中的作用

根据你提供的配置文件,让我们分析邮箱配置是如何发挥作用的:

1spring:
2  mail:
3    host: smtp.qq.com
4    username: 454284665@qq.com   # 登录账户
5    password: vdxewnwgchllbjha
6    port: 465
7    default-encoding: UTF-8
8    protocol: smtps
9

🔄 配置文件 → Spring容器 → Bean创建的完整流程

Step 1: Spring Boot启动时读取配置
1// Spring Boot会自动读取配置文件,创建MailProperties Bean
2@ConfigurationProperties(prefix = "spring.mail")
3public class MailProperties {
4    private String host;        // 自动映射 spring.mail.host
5    private String username;    // 自动映射 spring.mail.username  
6    private String password;    // 自动映射 spring.mail.password
7    private int port;           // 自动映射 spring.mail.port
8    // ... 其他属性
9}
10
Step 2: Spring Boot自动配置邮件服务
1// Spring Boot内置的邮件自动配置类(你看不到,但它在工作)
2@Configuration
3@ConditionalOnProperty(name = "spring.mail.host")  // 只有配置了host才生效
4public class MailSenderAutoConfiguration {
5    
6    @Bean
7    @ConditionalOnMissingBean(JavaMailSender.class)
8    public JavaMailSender javaMailSender(MailProperties properties) {
9        JavaMailSenderImpl sender = new JavaMailSenderImpl();
10        
11        // 使用你配置文件中的值
12        sender.setHost(properties.getHost());          // smtp.qq.com
13        sender.setPort(properties.getPort());          // 465
14        sender.setUsername(properties.getUsername());  // 454284665@qq.com
15        sender.setPassword(properties.getPassword());  // vdxewnwgchllbjha
16        sender.setProtocol(properties.getProtocol());  // smtps
17        
18        return sender;  // 创建好的邮件发送器放入Spring容器
19    }
20}
21
Step 3: 你的MailConfig可以直接使用
1@Configuration
2public class MailConfig {
3    
4    @Bean
5    public MailService mailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
6        // 这两个参数Spring会自动注入:
7        // 1. javaMailSender - 来自Step 2的自动配置
8        // 2. mailProperties - 来自Step 1的配置文件映射
9        return new MailService(javaMailSender, mailProperties);
10    }
11}
12

📋 配置文件的三种作用方式

方式1: 自动配置(最常用)
1spring:
2  mail:
3    host: smtp.qq.com      # Spring Boot自动创建JavaMailSender
4    username: xxx@qq.com   # 自动配置所有邮件相关Bean
5    password: xxx
6

结果: Spring容器自动有了JavaMailSender和MailProperties

方式2: 手动覆盖自动配置
1@Configuration
2public class MailConfig {
3    
4    // 如果你想自定义,可以手动创建,会覆盖自动配置
5    @Bean
6    @Primary  // 优先使用这个
7    public JavaMailSender customJavaMailSender() {
8        JavaMailSenderImpl sender = new JavaMailSenderImpl();
9        // 你的自定义配置...
10        return sender;
11    }
12}
13
方式3: 条件配置(我们之前讨论的)
1@Configuration
2public class MailConfig {
3    
4    // 只有在没有JavaMailSender时才创建
5    @Bean
6    @ConditionalOnMissingBean(JavaMailSender.class)
7    public JavaMailSender javaMailSender(Environment env) {
8        // 从Nacos等配置中心读取配置
9        return createCustomSender(env);
10    }
11}
12

🎯 你的配置文件的具体作用

1spring:
2  mail:
3    host: smtp.qq.com           # 邮件服务器地址
4    username: 454284665@qq.com  # 发送邮件的账号
5    password: vdxewnwgchllbjha  # QQ邮箱的授权码(不是QQ密码)
6    port: 465                   # SMTPS安全端口
7    default-encoding: UTF-8     # 邮件编码
8    protocol: smtps            # 使用SMTPS协议(SSL加密)
9

这些配置会自动变成:

1// Spring自动创建的MailProperties
2MailProperties mailProperties = new MailProperties();
3mailProperties.setHost("smtp.qq.com");
4mailProperties.setUsername("454284665@qq.com");
5mailProperties.setPassword("vdxewnwgchllbjha");
6mailProperties.setPort(465);
7mailProperties.setDefaultEncoding("UTF-8");
8mailProperties.setProtocol("smtps");
9
10// Spring自动创建的JavaMailSender
11JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
12javaMailSender.setHost("smtp.qq.com");
13javaMailSender.setUsername("454284665@qq.com");
14javaMailSender.setPassword("vdxewnwgchllbjha");
15javaMailSender.setPort(465);
16// ... 其他配置
17

🚀 完整的邮件发送流程

1// 1. 启动时:Spring读取配置文件
2spring.mail.host=smtp.qq.com
3spring.mail.username=454284665@qq.com
4           
5// 2. Spring自动创建Bean
6MailProperties + JavaMailSender  放入容器
7             
8// 3. 你的MailService使用
9@Resource
10private MailService mailService;  // 注入现成的
11
12public void sendEmail() {
13    mailService.sendRegisterCode("user@email.com", "123456");
14    // 内部使用你配置的QQ邮箱发送邮件
15}
16

💡 为什么要这样设计?

传统方式(每次手动配置):

1public void sendEmail() {
2    // 每次发邮件都要写这些!
3    JavaMailSenderImpl sender = new JavaMailSenderImpl();
4    sender.setHost("smtp.qq.com");
5    sender.setUsername("454284665@qq.com");
6    sender.setPassword("vdxewnwgchllbjha");
7    sender.setPort(465);
8    // ... 10行配置代码
9    
10    sender.send(message);  // 终于能发邮件了
11}
12

Spring方式(配置一次,到处使用):

1# 配置文件:写一次
2spring:
3  mail:
4    host: smtp.qq.com
5    username: 454284665@qq.com
6    password: vdxewnwgchllbjha
7
1// 业务代码:到处用
2@Resource
3private MailService mailService;
4
5public void sendEmail() {
6    mailService.sendRegisterCode("user@email.com", "123456");  // 一行搞定!
7}
8

🔐 安全提醒

你的配置中的password vdxewnwgchllbjha 是QQ邮箱的授权码,不是你的QQ密码。这是QQ邮箱为第三方应用提供的专用密码,更安全。

获取QQ邮箱授权码的步骤:

  1. 登录QQ邮箱
  2. 设置 → 账户
  3. 开启SMTP服务
  4. 获取授权码

🎯 总结:配置文件的核心价值

  1. 配置与代码分离:邮箱配置放在配置文件,代码更干净
  2. 环境适配:开发环境用测试邮箱,生产环境用正式邮箱
  3. Spring自动装配:配置文件 → 自动创建Bean → 直接注入使用
  4. 统一管理:所有邮件相关配置集中在一个地方

配置文件就是Spring的"原料清单",告诉Spring要准备什么材料,Spring根据清单自动准备好所有Bean供你使用!


Spring设计模式与依赖注入详解》 是转载文章,点击查看原文


相关推荐


多模态大模型有哪些模态?
智泊AI2026/1/6

“多模态”中的“模态”(modality),即指各类数据形式或信息来源。在多模态大模型中,典型模态涵盖以下类别: 更多AI大模型学习视频及资源,都在智泊AI。 文本模态‌: 涵盖自然语言文本、经语音识别转换的文本内容等。 图像模态‌: 指视觉图像数据,例如照片、插画、艺术作品等。 视频模态‌: 包含动态影像序列,如短视频、影视片段、监控录像等。 音频模态‌: 指声学信号数据,如人声、音乐、环境音效等。 其他模态‌: 还包括如环境传感器读数、生理信号、指纹、虹膜等非传统信息形式。 多模态模型的


旮旯c语言三个任务
宇宙超级无敌暴龙战士2025/12/29

#include <stdio.h> // 任务1:计算数组元素和 int getArrSum(int arr[], int len) { int sum = 0; for (int i = 0; i < len; i++) { sum += arr[i]; } return sum; } // 任务2:获取数组最大值 int getArrMax(int arr[], int len) { int max = arr[0]; f


python+django/flask+vue基于spark的西南天气数据的分析与应用系统
Q_Q5110082852025/12/19

目录 项目介绍本项目具体实现截图开发技术大数据类设计开发的基本流程是:论文大纲结论源码lw获取/同行可拿货,招校园代理 :文章底部获取博主联系方式! 项目介绍 系统功能 数据采集与清洗:系统通过爬虫技术从多个天气预报网站抓取西南地区的实时天气数据,并通过Spark SQL对数据进行并行计算,提取关键气象指标,并进行多维度分析,如空气质量、降水量、风速等。 数据处理与分析:系统利用Spark对天气数据进行分布式存储与处理,通过数据分析,实时展示西南地区的空气质量、温度变化、降水量、风


Flutter的核心优势
小a彤2025/12/11

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。#### Flutter:开发效率神器详解 Flutter作为Google推出的跨平台开发框架,凭借其高效的开发体验和出色的性能表现,成为众多开发者的首选。其核心优势在于"一次编写,多端运行"的核心理念,同时提供超过2000个现成的Widget组件库和强大的工具链,显著提升开发效率达30%-50%。 Flutter的核心优势 跨平台一致性 Flutter使用自绘引擎(Skia)直接渲染UI,完全避免了平台原生控件的依赖,确


Python学习笔记-Day4
@游子2025/12/2

Python学习笔记-Day4 判断与循环 条件判断if: 非常多的编程语言都会使用 if 关键字作为流程控制,除此之外,Python 3 的流程控制还包括 elif 和 else 两个关键字,这两个在选择控制中都是可选的。elif 的意思是 else if,增加进一步的判断是否选择该路径。 示例: # 当判断条件1为真时,执行语句1,否则为假就继续下一个判断条件 if 判断条件1: 执行语句1 elif 判断条件2: 执行语句2 elif 判断条件3: 执行语句3 else: 执行语


Verifier-state pruning in BPF
mounter6252026/1/22

The BPF verifier works, on a theoretical level, by considering every possible path that a BPF program could take. As a practical matter, however, it needs to do that in a reasonable amount of time. At the 2025 Linux Plumbers Conference, Mahé Tardy an

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客