我是 Spring 框架的新手,我在理解 @Required
时遇到了问题。注释与 Java 配置的应用程序相结合。
这是一个例子。
配置文件
@Configuration
public class AppConfig {
@Bean
public Movie movieA() {
return new Movie();
}
@Bean
public MovieHolder holder() {
return new MovieHolder();
}
}
MovieHolder.java
public class MovieHolder {
private Movie movie;
public Movie getMovie() {
return movie;
}
@Required
public void setMovie(Movie movie) {
this.movie = movie;
}
}
上下文初始化
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MovieHolder holder = (MovieHolder) context.getBean("holder");
System.out.println("movie: " + holder.getMovie());
据我了解
@Required
的文档注释,应该有一个异常(exception),因为电影不是直接设置的,也不是通过 Autowiring 的。取而代之的是输出 movie: null
.我究竟做错了什么?或者这不是
@Required
的正确用法吗?注解?
最佳答案
在您正在实例化的 bean 中设置所需的属性是您自己的责任。 BeanPostProcessor
处理用 @Configuration
注释的类中的 bean 定义被称为 ConfigurationClassPostProcessor
. BeanPostProcessor
处理您的 @Required
注释默认为 RequiredAnnotationBeanPostProcessor
, 使用 context:annotation-config
时默认注册和 context:component-scan
在您的配置中。如果你没有使用这两个标签,你甚至可以注册自己的 RequiredAnnotationBeanPostProcessor
作为 bean
.
现在, RequiredAnnotationBeanPostProcessor
的默认实现有一个方法叫 boolean shouldSkip(..)
检查名为 SKIP_REQUIRED_CHECK_ATTRIBUTE
的 bool 属性. RequiredAnnotationBeanPostProcessor
在后处理期间为每个 bean 检查此属性的值。 .如果返回 false
, @Required
强制执行约束,否则不执行。
现在, ConfigurationClassPostProcessor
将此属性的值设置为 true
从 @Configuration
创建 bean 定义时类(我猜是因为如果你定义一个 bean,你应该确保它具有所需的属性)。因此,@Required
不对此类 bean 强制执行。
顺便说一句,您可能会认为这是在哪里做的 SKIP_REQUIRED_CHECK_ATTRIBUTE
属性来自哪里以及它在哪里设置:它设置在 BeanDefinition
的实例上Spring 在内部使用它们来创建 bean 和进行后处理。
如果你真的想强制执行 @Required
约束,您必须覆盖 RequiredAnnotationBeanPostProcessor
,覆盖 boolean shouldSkip(..)
方法并注册这个类而不是默认的 RequiredAnnotationBeanPostProcessor
.而作为 RequiredAnnotationBeanPostProcessor
的文档说:
A default RequiredAnnotationBeanPostProcessor will be registered by the "context:annotation-config" and "context:component-scan" XML tags. Remove or turn off the default annotation configuration there if you intend to specify a custom RequiredAnnotationBeanPostProcessor bean definition.
另一种方法是使用
initMethod
您的 @Bean
上的属性注解。哪个可以执行检查以查看确实设置了所需的属性。但是,由于这是基于代码的配置,您也可以将其称为 init
自己方法。另外,在我看来,使用自己的
RequiredAnnotationBeanPostProcessor
经历很多麻烦没有多大意义。 ,如以下文档所述:Please note that an 'init' method may still need to implemented (and may still be desirable), because all that this class does is enforce that a 'required' property has actually been configured with a value. It does not check anything else... In particular, it does not check that a configured value is not null.
所以,总结一下:
@Required
不适用于 @Configuration
默认的类。如果您需要确保设置所有属性,您也可以在 @Bean
中创建 bean 时自己完成。方法(通过调用一些执行此类验证的 init
方法,或者只是自己提供所需的属性)。如果你真的需要制作 @Required
注释工作,您需要使用自己的 RequiredAnnotationBeanPostProcessor
实现,在spring上下文中注册为bean,放弃context:annotation-config
的好处.
关于spring - @Required 注释如何与 JavaConfig 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16769360/