源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Configuration
class MailConfig(
@param:Value($$"${spring.mail.host}")
private val host: String,

@param:Value($$"${spring.mail.port}")
private val port: Int = 0,

@param:Value($$"${spring.mail.username}")
private val username: String,

@param:Value($$"${spring.mail.password}")
private val password: String,

@param:Value($$"${spring.mail.protocol}")
private val protocol: String
) {
@Bean
fun javaMailSender(): JavaMailSender {
val sender = JavaMailSenderImpl()
sender.host = host
sender.port = port
sender.username = username
sender.password = password
sender.defaultEncoding = "Utf-8"
sender.protocol = protocol
return sender
}
}

运行时报错 Failed to instantiate ... MailConfig$$SpringCGLIB$$0: No default constructor found ,原因是当有默认值时,编译出来的java会生成多个构造器,而spring不知道该用哪个构造器,于是回退尝试调用无参构造器,结果发现不存在,就抛出异常了。

(编译后的java)

解决办法就是不要在bean的构造器上写默认值。此外如果没有引用到其他bean,写成 @Configuration(proxyBeanMethods = false) 禁用bean方法代理的同时提升点性能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@Configuration(proxyBeanMethods = false)
class MailConfig(
@param:Value($$"${spring.mail.host}")
private val host: String,

@param:Value($$"${spring.mail.port:0}") // 其实默认值更应该写在application.yml里
private val port: Int,

@param:Value($$"${spring.mail.username}")
private val username: String,

@param:Value($$"${spring.mail.password}")
private val password: String,

@param:Value($$"${spring.mail.protocol}")
private val protocol: String
) {
@Bean
fun javaMailSender(): JavaMailSender {
val sender = JavaMailSenderImpl()
sender.host = host
sender.port = port
sender.username = username
sender.password = password
sender.defaultEncoding = "Utf-8"
sender.protocol = protocol
return sender
}
}