How does @Required annotation work with JavaConfig?

I'm new to the Spring Framework, and I'm having trouble understanding @Required annotation in conjunction with a customized Java application.

Here is an example.

Config file

 @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; } } 

Context initialization

 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); MovieHolder holder = (MovieHolder) context.getBean("holder"); System.out.println("movie: " + holder.getMovie()); 

As far as I understood the @Required annotation @Required , an exception should occur because the movie is not installed directly or by auto-notification. Instead, movie: null is output.

What am I doing wrong? Or is it the misuse of @Required annotation?

+8
spring annotations required
source share
2 answers

Setting the necessary properties in the beans that you create is your own responsibility. BeanPostProcessor that handles bean -definitions in classes annotated with @Configuration is called ConfigurationClassPostProcessor . BeanPostProcessor that processes your @Required annotations by default 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 .

Now the default implementation of RequiredAnnotationBeanPostProcessor has a method called boolean shouldSkip(..) that checks a boolean attribute called SKIP_REQUIRED_CHECK_ATTRIBUTE . The value of this attribute is checked for each bean during subsequent processing of RequiredAnnotationBeanPostProcessor . If it returns false , the forced restriction is @Required , otherwise it is not.

Now ConfigurationClassPostProcessor sets the value of this attribute to true when creating bean definitions from the @Configuration classes (I think for the reason that if you define a bean, you have to make sure that it has the necessary properties). Therefore, @Required not applicable for such beans.

As an aside, you might wonder where this SKIP_REQUIRED_CHECK_ATTRIBUTE attribute came from: where it is installed: it is installed in the BeanDefinition instances that Spring uses for the bean to create and process.

If you really want to apply @Required restrictions, you will have to override RequiredAnnotationBeanPostProcessor , override the boolean shouldSkip(..) method, and register this class instead of the default RequiredAnnotationBeanPostProcessor . And the documentation for RequiredAnnotationBeanPostProcessor says:

The required RequiredAnnotationBeanPostProcessor will be registered by default with the XML tags "context: annotation-config" and "context: component-scan". Remove or disable the default annotation configuration there if you intend to specify a custom definition of RequiredAnnotationBeanPostProcessor bean.

Another way is to use the initMethod attribute in your @Bean annotation. Which could carry out checks to make sure that the required properties are indeed set. However, since this is a code-based configuration, you can just call this init method like that.

In addition, in my opinion, there are not many problems with using your own RequiredAnnotationBeanPostProcessor , as indicated in the following documentation:

Note that the init method may still need to be implemented (and may still be desirable), because everything that this class does does enforce that the "required" property is indeed configured with a value. It does not check anything ... In particular, it does not verify that the configured value is not null.

So, to summarize: @Required does not work with @Configuration classes by @Configuration . If you need to make sure that all your properties are set, you can also do it yourself when you create a bean in @Bean methods (by calling the init method, which performs such checks, or simply by supplying the necessary properties). And if you really need to make the @Required annotation, you will need to use your own implementation of RequiredAnnotationBeanPostProcessor , register it as a bean in the Spring context, and discard the benefits of context:annotation-config .

+8
source share

Just tried declaring @ Bean RequiredAnnotationBeanPostProcessor with an overridden shouldSkip () method.

Yes, it checks my beans, but it fails even if I set all the necessary properties, i.e. he always fails.
I think Spring has a real problem with @Required annotation support for Java Config, since Spring has no way to determine if a property is set when you do it directly in Java code. (He cannot check the "null" fields later, as this would mean changing the semantics of the @Required annotation, which should allow explicit nulling).

When you use the XML configuration, Spring creates a wrapper object to set properties, so it can track all configured setXxx () operations.

Conclusion : There is no reasonable way to include @Required annotations for beans created in Java @Configuration.
(A very unsuccessful function, in my opinion, since the writer of the bean class and the user of the class can be different persons).

+1
source share

All Articles