问题描述
我对Spring Framework还是很陌生,在理解@Required
注释与Java配置的应用程序结合使用时遇到了问题.
I'm pretty new to the Spring Framework and I got problems to understand the @Required
annotation in combination with a Java configured application.
这里是一个例子.
配置文件
@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
注释的文档,应该出现一个例外,因为电影不是直接设置的,也不是通过自动装配设置的.而是输出movie: null
.
As far as I understood the documentation of the @Required
annotation, there should rise an exception, because movie isn't set directly or by autowiring. Instead is the output movie: null
.
我做错了什么?还是这不是@Required
注释的正确用法?
What am I doing wrong? Or isn't this the correct use of the @Required
annotation?
推荐答案
在您要实例化的bean中设置必需的属性是您自己的责任. BeanPostProcessor
一个在@Configuration
注释的类中处理bean定义的a>称为 ConfigurationClassPostProcessor
. BeanPostProcessor
处理您的@Required
批注的a>默认为 RequiredAnnotationBeanPostProcessor
,当您在配置中使用context:annotation-config
和context:component-scan
时默认注册.如果您不使用这两个标记,则甚至可以注册自己的作为bean
.
Setting the required properties in the beans that you are instantiating is your own responsibility. The BeanPostProcessor
that processes the bean-definitions in the classes annotated with @Configuration
is called ConfigurationClassPostProcessor
. The BeanPostProcessor
that processes your @Required
annotation defaults to RequiredAnnotationBeanPostProcessor
, which is registered by default when you use context:annotation-config
and context:component-scan
in your configuration. If you are not using these two tags, you can even register your own RequiredAnnotationBeanPostProcessor
as a bean
.
现在,具有称为boolean shouldSkip(..)
的方法,该方法检查名为.在.如果它返回false
,则强制执行@Required
约束,否则则不执行.
Now, the default implementation of the RequiredAnnotationBeanPostProcessor
has a method called boolean shouldSkip(..)
that checks for a boolean attribute named SKIP_REQUIRED_CHECK_ATTRIBUTE
. The value of this attribute is checked for each bean during the post-processing by the RequiredAnnotationBeanPostProcessor
. If it returns false
, the @Required
constraint is enforced, otherwise it is not.
现在, ConfigurationClassPostProcessor
在通过@Configuration
类创建Bean定义时,将此属性的值设置为true
(我猜是因为,如果 you 定义一个bean,则 you 应该确保它具有必需的属性).因此,对于这样的bean不执行@Required
.
Now, the ConfigurationClassPostProcessor
set the value of this attribute to true
while creating the bean definitions from the @Configuration
classes (I guess for the reason that if you are defining a bean, you should ensure that it has the required properties). Hence, the @Required
is not enforced for such beans.
顺便说一句,您可能会认为属性的来源和设置位置:该属性在进行Bean创建和后处理.
As an aside, You might think that where did this SKIP_REQUIRED_CHECK_ATTRIBUTE
attribute come from and where is it set: it is set on the instances of BeanDefinition
that are used by Spring internally for bean creation and post-processing.
如果您确实要强制执行@Required
约束,则必须覆盖,覆盖boolean shouldSkip(..)
方法并注册该类,而不是默认的.并且作为 RequiredAnnotationBeanPostProcessor
的文档说:
If you really want to enforce the @Required
constraints, you would have to override the RequiredAnnotationBeanPostProcessor
, override the boolean shouldSkip(..)
method and register this class instead of the default RequiredAnnotationBeanPostProcessor
. And as the documentation for RequiredAnnotationBeanPostProcessor
says:
另一种方法是在@Bean
批注上使用initMethod
属性.它可以执行检查以确保确实设置了必需的属性.但是,由于这是基于代码的配置,因此您也可以自己调用该init
方法.
Another way would be to use the initMethod
attribute on your @Bean
annotation. Which could perform checks to see that the required properties are indeed set. However, since this is code based configuration, you could just as well call that init
method yourself.
在我看来,使用自己的,如以下文档所述:
Also, in my opinion, there is not much point in going through a lot of trouble to use your own RequiredAnnotationBeanPostProcessor
, as the following documentation says:
因此,总结一下: @Required
默认情况下不适用于@Configuration
类.如果需要确保所有属性都已设置,那么在@Bean
方法中创建bean时也可以自己进行设置(通过调用执行此类验证的某些init
方法,或者仅提供必需的)即可.自行设定).而且,如果您真的需要使@Required
注释生效,则需要使用自己的,在Spring上下文中将其注册为Bean,并放弃context:annotation-config
的优点
So, to summarize: @Required
doesn't work with @Configuration
classes by default. If you need to make sure that all your properties are set, you can just as well do it yourself when you create the bean in the @Bean
methods (By calling some init
method that performs such validations, or just supplying the required properties yourself). And if you really need to make the @Required
annotation work, you'd need to use your own implementation of the RequiredAnnotationBeanPostProcessor
, register it as a bean in the spring context and give up the benefits of context:annotation-config
.
这篇关于@Required注释如何与JavaConfig一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!