1. 复现问题
今天使用@SpringBootTest
测试发送邮件,如下代码所示:
@SpringBootTest
class SuperJsonManagerApplicationTests {
@Test
void contextLoads() {
}
@Autowired
private MailConfig mailConfig;
@Test
public void testSendMail() {
MailPo mailPo=new MailPo();
mailPo.setTo(new String[];
mailPo.setSubject("测试发送邮件");
mailPo.setText("这封邮件能否发送出去,验证码为: <code>1233</code>");
mailConfig.sendSimpleMail(mailPo);
}
}
但启动时,报出如下错误:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mailConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.mail.username' in value "${spring.mail.username}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:601)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:438)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:337)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:123)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
... 67 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.mail.username' in value "${spring.mail.username}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:180)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:936)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1321)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
... 83 more
即nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.mail.username' in value "${spring.mail.username}"
该问题。
2. 分析问题
上述问题是无法解析值${spring.mail.username}
中的占位符spring.mail.username
。
2.1 检查yml配置
如下是在application-local.yml
文件中配置邮件信息:
spring:
#发送邮箱配置
mail:
# 邮件服务器地址
host: ""
# 你的邮箱地址
username: "你的邮箱"
# 授权码
password: "你的授权码"
# 编码格式
default-encoding: utf-8
# 协议
protocol: smtp
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
没有发现问题
2.2 检查依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
没有发现依赖存在问题
2.3 检查启动
yml配置文件和依赖都没有问题,启动项目看没有问题,如下图所示:
通过这种方式,能正常启动项目,只能说明@SpringBootTest
注解有问题。
3. 解决问题
既然知道是@SpringBootTest
注解有问题,导致无法读取yml
中的配置文件,那么,就要修改@SpringBootTest
注解,如下所示:
// 指定需要加载的配置文件,比如application-local.yml
@ActiveProfiles("local")
// 修改启动环境
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SuperJsonManagerApplicationTests {
@Test
void contextLoads() {
}
@Autowired
private MailConfig mailConfig;
@Ignore
public void testSendMail() {
MailPo mailPo=new MailPo();
mailPo.setTo(new String[]{"144xxx@"});
mailPo.setSubject("测试发送邮件");
mailPo.setText("这封邮件能否发送出去,验证码为: <code>1233</code>");
mailConfig.sendSimpleMail(mailPo);
}
}
重新测试发送邮件方法,此时可以正常收到邮件,如下图所示:
4. 问题总结
出现这种问题,一般是没有正确加载配置文件造成的,比如application.yml
或者application.properties
文件,导致spring无法读取配置文件中的数据,而无法使用@Value注解
初始化数据。