问题描述
我花了一些时间解决Spring Data中缺少org.joda.time.DateTime->java.util.Date
转换器的问题(当Joda-Time在类路径上时,默认情况下应启用该转换器).我找到了一个原因,但是它在Spring中产生了关于@Configuration
批注的问题.
I spent some time resolving problem with missing org.joda.time.DateTime->java.util.Date
converter in Spring Data (which should be enabled by default when Joda-Time is on a classpath). I have found a reason, but it generated a question about @Configuration
annotation in Spring.
使用spring-data-mongodb中的AbstractMongoConfiguration
的标准应用程序配置:
Standard application config using AbstractMongoConfiguration
from spring-data-mongodb:
@Configuration
@ComponentScan
@EnableMongoRepositories
public class AppConfig extends AbstractMongoConfiguration { ... }
显式使用AppConfig类的测试(使用Spock,但内部使用spring-test提供的机制):
A test which explicit uses AppConfig class (with Spock, but internally mechanisms provided by spring-test are used):
@ContextConfiguration(classes = AppConfig)
class JodaDocRepositorySpec extends Specification {
@Autowired
private JodaDocRepository jodaDocRepository
def "save document with DateTime"() {
given:
def jodaDoc = new JodaDoc(DateTime.now())
when:
def savedJodaDoc = jodaDocRepository.save(jodaDoc)
then:
savedJodaDoc.id
}
}
工作正常.但是,当删除/注释了AppConfig中的@Configuration批注时:
It works fine. But when @Configuration annotation in AppConfig is removed/commented:
//@Configuration
@ComponentScan
@EnableMongoRepositories
public class AppConfig extends AbstractMongoConfiguration { ... }
测试失败:
org.springframework.core.convert.ConverterNotFoundException:
No converter found capable of converting from type org.joda.time.DateTime to type java.util.Date
AFAIK,当在上下文中显式注册配置类时,不需要对配置类使用@Configuration
(通过@ContextConfiguration
中的类或AnnotationConfigWebApplicationContext
中的register()
方法).无论如何,都将处理这些类,并且会找到所有已声明的bean.在不同测试使用的测试上下文中,同一程序包中有2个相似的配置类时,有时不使用@Configuration
来防止通过组件扫描进行检测是很有用的.
AFAIK it is not needed to use @Configuration
for the configuration class when it is explicit registered in the context (by classes in @ContextConfiguration
or a register()
method in AnnotationConfigWebApplicationContext
). The classes are processed anyway and all declared beans are found. It is sometimes useful to not use @Configuration
to prevent detecting by a component scan when there are 2 similar configuration classes in the same packages in a test context used by different tests.
因此,我认为这可能是Spring中的错误,根据使用情况或@Configuration
批注,这会导致上下文中不同的内部bean处理.我比较了这两种情况下的Spring日志,但有一些区别,但是我无法确定它们在Spring内部类中是由什么引起的.在提交错误之前,我想问一下:
Therefor I think it could a bug in Spring which causes to different internal beans processing in the context depending on an usage or not a @Configuration
annotation. I compared Spring logs from these two cases and there are some differences, but I'm not able to determine what are they caused by in the Spring internal classes. Before a bug submission I would like to ask:
我的问题.是否存在一个明确的原因,即为什么针对同一配置类(在@ContextConfiguration
中明确指出)的Spring使用(或不使用)Joda-Time转换器,具体取决于是否存在@Configuration
批注?
My question. Is there an explicable reason why Spring for the same configuration class (pointed explicit in @ContextConfiguration
) uses (or not) converters for Joda-Time depending on an existence of a @Configuration
annotation?
我还创建了一个 quickstart项目重现了该问题. spring-data-mongodb 1.3.3,spring 4.0.0,joda-time 2.3.
I created also a quickstart project reproducing the issue. spring-data-mongodb 1.3.3, spring 4.0.0, joda-time 2.3.
推荐答案
在此行为中,一切正常. AbstractMongoConfiguration
由@Configuration
注释,但实际上该注释不是@Inherited
,因此您必须显式注释您的类.
It's everything OK in this behaviour. AbstractMongoConfiguration
is annotated by @Configuration
, but in fact this annotation is not @Inherited
, so you have to explicitly annotate your class.
删除@Configuration
批注时,您的AppConfig
类不是完整配置.由于它包含@Bean
注释的方法,因此它是 lite 配置的过程-请参考org.springframework.context.annotation.ConfigurationClassUtils
When you remove @Configuration
annotation then your AppConfig
class is not a full configuration. It's processes as a lite configuration just because it contains methods annotated by @Bean
- please refer to methods in org.springframework.context.annotation.ConfigurationClassUtils
-
isFullConfigurationCandidate()
-
isLiteConfigurationCandidate()
-
isFullConfigurationClass()
isFullConfigurationCandidate()
isLiteConfigurationCandidate()
isFullConfigurationClass()
最后,只有完整个配置类(由@Configuration
注释)是进程,并由配置后处理器增强-请查看ConfigurationClassPostProcessor.enhanceConfigurationClasses()
Finally only full (annotated by @Configuration
) configuration classes are processes and enhanced by configuration post processors - look at ConfigurationClassPostProcessor.enhanceConfigurationClasses()
这篇关于我应该将配置类注释为@Configuration进行测试吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!