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

📚 前言

这是我之前写 项目时的一些理解和感悟, 我喊了AI帮我润色了一下语言文字,发出来了,希望对大家有用

在学习Spring框架时,经常会遇到@Configuration@Bean@Service@Resource等注解,以及各种设计模式的应用。本文通过具体的代码示例(MailConfigMailService),深入浅出地解释这些概念,帮助理解Spring的核心机制。

🎯 核心问题

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

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

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

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

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


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

🤔 没有Spring的痛苦

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

没有Spring配置的代码:

java 复制代码
// 第1个地方:用户注册
public void register() {
    // 每次都要写这一堆配置!
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    sender.setHost("smtp.qq.com");
    sender.setPort(587);
    sender.setUsername("myemail@qq.com");
    sender.setPassword("mypassword");
    
    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.ssl.enable", "true");
    props.put("mail.smtp.timeout", "5000");
    props.put("mail.smtp.connectiontimeout", "5000");
    props.put("mail.smtp.writetimeout", "5000");
    sender.setJavaMailProperties(props);
    
    MailProperties mailProps = new MailProperties();
    mailProps.setUsername("myemail@qq.com");
    // ... 更多配置
    
    MailService mailService = new MailService(sender, mailProps);
    mailService.sendRegisterCode("user@email.com", "123456");
}

// 第2个地方:密码重置
public void resetPassword() {
    // 又要写一遍同样的15行配置!!!
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    sender.setHost("smtp.qq.com");  // 重复!
    sender.setPort(587);            // 重复!
    sender.setUsername("myemail@qq.com");  // 重复!
    // 又是15行重复配置...
    
    MailService mailService = new MailService(sender, mailProps);
    mailService.sendResetEmail("user@email.com");
}

// 第3个地方:系统通知
public void sendNotification() {
    // 再写一遍同样的15行配置!!!
    // 同样的重复代码...
}

问题有多严重?

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

Spring的解决方案:仓库管理

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

java 复制代码
@Configuration  // "我是配置管理员"
public class MailConfig {
    
    @Bean  // "我来准备现成的MailService放到仓库"
    public MailService mailService(JavaMailSender sender, MailProperties props) {
        // 复杂配置我来写,你不用管
        return new MailService(sender, props);  // 现成的产品放入仓库
    }
    
    @Bean  // "我来准备现成的JavaMailSender放到仓库"
    public JavaMailSender javaMailSender() {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost(env.getProperty("spring.mail.host"));
        sender.setPort(Integer.parseInt(env.getProperty("spring.mail.port", "25")));
        sender.setUsername(env.getProperty("spring.mail.username"));
        sender.setPassword(env.getProperty("spring.mail.password"));
        
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.ssl.enable", "true");
        props.put("mail.smtp.timeout", "5000");
        sender.setJavaMailProperties(props);
        
        return sender;  // 现成的邮件发送器放入仓库
    }
}

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

java 复制代码
// 第1个地方:用户注册
@Resource
private MailService mailService;  // 从仓库提货

public void register() {
    mailService.sendRegisterCode("user@email.com", "123456");  // 一行搞定!
}

// 第2个地方:密码重置  
@Resource
private MailService mailService;  // 还是从仓库提货

public void resetPassword() {
    mailService.sendResetEmail("user@email.com");  // 一行搞定!
}

// 第3个地方:系统通知
@Resource  
private MailService mailService;  // 依然从仓库提货

public void sendNotification() {
    mailService.sendNotification("通知内容");  // 一行搞定!
}

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

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

java 复制代码
@Service  // ← 这就像给盒子贴了"请放入仓库"的标签
public class UserService {
    public void doSomething() {
        // 业务逻辑
    }
}

@Controller  // ← 另一种标签
public class UserController {
}

@Repository  // ← 又一种标签
public class UserRepository {
}

工作流程:

复制代码
Spring启动 → 扫描所有类 → 发现@Service标签 → 自动创建UserService → 放入仓库

🚚 方式2:手动搬运入库

java 复制代码
// MailService没贴标签,Spring不会自动放入
public class MailService {
    private final JavaMailSender javaMailSender;
    private final MailProperties mailProperties;
    
    public MailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
        this.javaMailSender = javaMailSender;
        this.mailProperties = mailProperties;
    }
}

@Configuration
public class MailConfig {
    @Bean  // ← 这里是"搬运工",手动把MailService放入仓库
    public MailService mailService(JavaMailSender sender, MailProperties props) {
        MailService service = new MailService(sender, props);  // 手动创建
        return service;  // 手动放入仓库
    }
}

工作流程:

复制代码
Spring启动 → 发现MailConfig → 看到@Bean方法 → 调用这个方法 → 得到MailService → 放入仓库

🛍️ 从仓库取货

java 复制代码
@Resource  // "仓库管理员,给我一个MailService"
private MailService mailService;  // Spring从仓库里拿给你

// Spring不关心这个东西是怎么进仓库的(贴标签还是手动搬运)
// 只要仓库里有,就能给你

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


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

📋 MailService的需求清单

java 复制代码
public class MailService {
    private final JavaMailSender javaMailSender;  // 需求1:我要一个邮件发送器
    private final MailProperties mailProperties;  // 需求2:我要一个配置信息
    
    // 构造函数 = "需求清单"
    public MailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
        this.javaMailSender = javaMailSender;  // 收下需求1
        this.mailProperties = mailProperties;  // 收下需求2
    }
    
    public void sendRegisterCode(String to, String code) throws Exception {
        // 使用构造函数收到的 javaMailSender 发邮件
        MimeMessage message = javaMailSender.createMimeMessage();
        
        // 使用构造函数收到的 mailProperties 获取配置
        MimeMessageHelper helper = new MimeMessageHelper(message, false);
        helper.setFrom(mailProperties.getUsername());
        helper.setTo(to);
        helper.setSubject("注册验证码通知");
        
        String content = buildRegisterTemplate(code);
        helper.setText(content, true);
        
        javaMailSender.send(message);  // 发送邮件
    }
}

🏭 MailConfig = 材料供应商

java 复制代码
@Configuration
public class MailConfig {
    
    @Bean
    public MailService mailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
        //                          ↑ 材料1: Spring自动提供   ↑ 材料2: Spring自动提供
        
        // Spring调用这个方法时会自动传入这两个参数
        return new MailService(javaMailSender, mailProperties);
        //                     ↑ 把材料1给MailService    ↑ 把材料2给MailService
    }
}

🔄 完整的供需匹配过程

Step 1: MailService提出需求

java 复制代码
public MailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
    // "要造我,必须给我这两样材料"
}

Step 2: Spring准备材料

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

Step 3: MailConfig组装

java 复制代码
@Bean
public MailService mailService(JavaMailSender sender, MailProperties props) {
    // Spring: "我把准备好的材料传给你"
    // MailConfig: "好的,我用这些材料造MailService"
    return new MailService(sender, props);  // 用材料造产品
}

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

java 复制代码
public void sendRegisterCode(String to, String code) {
    // 使用构造函数收到的现成材料工作,不用自己创建
    javaMailSender.send(message);
}

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

错误做法:MailService自己找材料

java 复制代码
public class MailService {
    public void sendRegisterCode(String to, String code) {
        // 每次都要自己创建!很麻烦!很容易出错!
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost("smtp.qq.com");
        sender.setPort(587);
        sender.setUsername("myemail@qq.com");
        sender.setPassword("mypassword");
        // ... 15行重复配置代码
        
        sender.send(message);
    }
}

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

java 复制代码
public class MailService {
    private final JavaMailSender javaMailSender;  // 别人给我准备好的
    
    public MailService(JavaMailSender javaMailSender) {
        this.javaMailSender = javaMailSender;  // 接收别人准备的
    }
    
    public void sendRegisterCode(String to, String code) {
        javaMailSender.send(message);  // 直接用,不用自己配置
    }
}

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

1. 🏭 工厂模式(Factory Pattern)

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

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

java 复制代码
// MailConfig = 邮件服务工厂
@Configuration
public class MailConfig {
    
    @Bean  // 工厂方法:专门创建MailService
    public MailService mailService(JavaMailSender sender, MailProperties props) {
        // 复杂的创建逻辑集中在这里
        return new MailService(sender, props);
    }
    
    @Bean  // 工厂方法:专门创建JavaMailSender
    public JavaMailSender javaMailSender() {
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        // 复杂的配置逻辑
        sender.setHost(env.getProperty("spring.mail.host"));
        sender.setPort(Integer.parseInt(env.getProperty("spring.mail.port")));
        // ... 更多复杂配置
        return sender;
    }
}

工厂模式的好处:

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

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

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

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

java 复制代码
// 错误做法:高耦合
public class MailService {
    public void sendMail() {
        // 自己创建依赖,高耦合!
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost("smtp.gmail.com");  // 写死了配置
        sender.send();
    }
}

// 正确做法:依赖注入
public class MailService {
    private final JavaMailSender javaMailSender;  // 依赖
    
    // 构造器注入:外部传入依赖
    public MailService(JavaMailSender javaMailSender) {
        this.javaMailSender = javaMailSender;
    }
    
    public void sendMail() {
        javaMailSender.send();  // 使用注入的依赖,低耦合!
    }
}

依赖注入的好处:

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

3. 🎯 策略模式(Strategy Pattern)

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

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

java 复制代码
@Configuration
public class MailConfig {
    
    // 策略1:优先使用Spring Boot自动配置的JavaMailSender
    @Bean
    @ConditionalOnMissingBean(MailService.class)  // 条件:如果还没有MailService
    public MailService mailService(JavaMailSender javaMailSender, MailProperties mailProperties) {
        return new MailService(javaMailSender, mailProperties);
    }

    // 策略2:如果没有JavaMailSender,自己创建一个
    @Bean
    @ConditionalOnMissingBean(JavaMailSender.class)  // 条件:如果还没有JavaMailSender
    public JavaMailSender javaMailSender() {
        // 从Environment读取Nacos配置,创建自定义的邮件发送器
        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setHost(env.getProperty("spring.mail.host"));
        // ... 从配置中心读取配置
        return sender;
    }
}

策略模式的体现:

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

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

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

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

java 复制代码
@Bean
public JavaMailSender javaMailSender() {
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    
    // 适配器:将Environment配置适配到JavaMailSender接口
    sender.setHost(env.getProperty("spring.mail.host"));           // 适配host
    sender.setPort(Integer.parseInt(env.getProperty("spring.mail.port", "25"))); // 适配port  
    sender.setUsername(env.getProperty("spring.mail.username"));   // 适配username
    sender.setPassword(env.getProperty("spring.mail.password"));   // 适配password
    
    // 适配Properties配置
    Properties props = new Properties();
    String timeout = env.getProperty("spring.mail.properties.mail.smtp.timeout", "5000");
    props.put("mail.smtp.timeout", timeout);
    sender.setJavaMailProperties(props);
    
    return sender;
}

适配器模式的体现:

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

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

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

复制代码
1. Spring Boot启动
   ↓
2. 扫描AutoConfiguration.imports文件  
   ↓
3. 发现MailConfig配置类
   ↓
4. 处理@Bean方法:
   - 检查:容器中有JavaMailSender吗?
     * 有 → 直接使用
     * 没有 → 调用javaMailSender()方法创建
   ↓  
5. 处理@Bean方法:
   - 检查:容器中有MailService吗?
     * 有 → 跳过
     * 没有 → 调用mailService()方法创建
   ↓
6. 将创建的Bean存储到Spring容器中
   ↓
7. 启动完成,Bean准备就绪

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

java 复制代码
@Service
public class UserService {
    
    @Resource  // 1. Spring看到@Resource注解
    private MailService mailService;  // 2. 从容器中查找MailService
                                     // 3. 找到后注入到这个字段
    
    public void registerUser(String email) {
        // 4. 直接使用注入的MailService,一行搞定
        mailService.sendRegisterCode(email, "123456");
    }
}

🎯 关键理解

  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工厂方法,缺一不可。


🚀 第八部分:扩展应用

📦 类似的配置示例

java 复制代码
// 阿里云短信配置
@Configuration
public class AliSmsConfig {
    
    @Bean("aliClient")
    public Client client() {
        Config config = new Config()
            .setAccessKeyId(accessKeyId)
            .setAccessKeySecret(accessKeySecret)
            .setEndpoint(endpoint);
        return new Client(config);  // 复杂对象创建
    }
}

// 数据库配置  
@Configuration
public class DatabaseConfig {
    
    @Bean
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost/db");
        dataSource.setUsername("user");
        dataSource.setPassword("pass");
        dataSource.setMaximumPoolSize(20);  // 复杂配置
        return dataSource;
    }
}

🎯 最佳实践

  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中的作用

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

yaml 复制代码
spring:
  mail:
    host: smtp.qq.com
    username: 454284665@qq.com   # 登录账户
    password: vdxewnwgchllbjha
    port: 465
    default-encoding: UTF-8
    protocol: smtps

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

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

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

方式1: 自动配置(最常用)
yaml 复制代码
spring:
  mail:
    host: smtp.qq.com      # Spring Boot自动创建JavaMailSender
    username: xxx@qq.com   # 自动配置所有邮件相关Bean
    password: xxx

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

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

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

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

这些配置会自动变成:

java 复制代码
// Spring自动创建的MailProperties
MailProperties mailProperties = new MailProperties();
mailProperties.setHost("smtp.qq.com");
mailProperties.setUsername("454284665@qq.com");
mailProperties.setPassword("vdxewnwgchllbjha");
mailProperties.setPort(465);
mailProperties.setDefaultEncoding("UTF-8");
mailProperties.setProtocol("smtps");

// Spring自动创建的JavaMailSender
JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
javaMailSender.setHost("smtp.qq.com");
javaMailSender.setUsername("454284665@qq.com");
javaMailSender.setPassword("vdxewnwgchllbjha");
javaMailSender.setPort(465);
// ... 其他配置

🚀 完整的邮件发送流程

java 复制代码
// 1. 启动时:Spring读取配置文件
spring.mail.host=smtp.qq.com
spring.mail.username=454284665@qq.com
           ↓
// 2. Spring自动创建Bean
MailProperties + JavaMailSender → 放入容器
           ↓  
// 3. 你的MailService使用
@Resource
private MailService mailService;  // 注入现成的

public void sendEmail() {
    mailService.sendRegisterCode("user@email.com", "123456");
    // 内部使用你配置的QQ邮箱发送邮件
}

💡 为什么要这样设计?

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

java 复制代码
public void sendEmail() {
    // 每次发邮件都要写这些!
    JavaMailSenderImpl sender = new JavaMailSenderImpl();
    sender.setHost("smtp.qq.com");
    sender.setUsername("454284665@qq.com");
    sender.setPassword("vdxewnwgchllbjha");
    sender.setPort(465);
    // ... 10行配置代码
    
    sender.send(message);  // 终于能发邮件了
}

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

yaml 复制代码
# 配置文件:写一次
spring:
  mail:
    host: smtp.qq.com
    username: 454284665@qq.com
    password: vdxewnwgchllbjha
java 复制代码
// 业务代码:到处用
@Resource
private MailService mailService;

public void sendEmail() {
    mailService.sendRegisterCode("user@email.com", "123456");  // 一行搞定!
}

🔐 安全提醒

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

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

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

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

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

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

相关推荐
sxlishaobin2 小时前
设计模式之组合模式
设计模式·组合模式
ExiFengs2 小时前
Java使用策略模式实现多实体通用操作的优雅设计
java·开发语言·设计模式·策略模式
茶本无香2 小时前
设计模式之三—工厂模式:灵活对象创建的艺术
java·开发语言·设计模式·工厂模式
week_泽2 小时前
第7课:管理长期记忆的关键架构决策 - 学习笔记_7
java·笔记·学习·ai agent
爱装代码的小瓶子2 小时前
【c++进阶】c++11下类的新变化以及Lambda函数和封装器
java·开发语言·c++
乌萨奇也要立志学C++2 小时前
【Linux】线程同步 条件变量精讲 + 生产者消费者模型完整实现
java·linux·运维
澄澈青空~2 小时前
病毒木马侵入系统内核的底层运作机理
java·linux·服务器
lkbhua莱克瓦242 小时前
进阶-存储对象2-存储过程上
java·开发语言·数据库·sql·mysql
杨杨杨大侠2 小时前
深入理解 LLVM:从编译器原理到 JIT 实战
java·jvm·编译器