Home > Net >  Why some abstract class has spring @Configuration annotation?
Why some abstract class has spring @Configuration annotation?

Time:09-30

This is an example for the question. (spring-data-r2dbc)

package org.springframework.data.r2dbc.config;

@Configuration(proxyBeanMethods = false)
public abstract class AbstractR2dbcConfiguration implements ApplicationContextAware {
...
}

According to my common sense, an abstract class cannot be registered as a bean even if it has @Configuration. And since @Configuration does not have @Inherited, the object of the inheriting class is not automatically registered as a bean, so we have to add @Configuration directly for the inheriting class. I'm curious as to why some abstract class has @Configuration annotation like the code above.

CodePudding user response:

I looked up some information and found that abstract classes are allowed.

The constraints in the documentation do not say that abstract classes or interfaces(can?) do not support Configuration annotations

Configuration annotation

Constraints when authoring @Configuration classes

  • Configuration classes must be provided as classes (i.e. not as instances returned from factory methods), allowing for runtime enhancements through a generated subclass.
  • Configuration classes must be non-final (allowing for subclasses at runtime), unless the proxyBeanMethods flag is set to false in which case no runtime-generated subclass is necessary.
  • Configuration classes must be non-local (i.e. may not be declared within a method).
  • Any nested configuration classes must be declared as static.
  • @Bean methods may not in turn create further configuration classes (any such instances will be treated as regular beans, with their configuration annotations remaining undetected).

Like this question, i hope there are powerful guys who can explain this problem from the perspective of source code. Because apart from the instructions in the documentation, I don't know what the reason is yet.


I tested repeatedly for an afternoon and found that adding Configuration annotations to abstract classes does not seem to have any effect, What seems to be valid is just the annotation on the final subclass.

Here is the codes!!! firse, we need a interface TestInterface.java:

public interface TestInterface {                                                                         
    public String hello();                                                                                         
    public String hello1();                                                                                        
}   

then make a abstract class MyConfigration.java:

//@Configuration(proxyBeanMethods = false)
//@Configuration
public abstract class MyConfigration implements TestInterface  {      
    @Bean                                                                       
    public String hello() {                                                     
        System.out.println("call hello in super class");                        
        return "hello";                                                                           
    }                                                                                                                                                 
}

and last, we need a subclass SubMyConfigration.java

@Configuration                                                                  
class SubMyConfigration extends MyConfigration {                              
    @Bean                                                                       
    public String hello1() {                                                    
        return " hello1 from subclass";                                         
    }                                                                           
}  

use the mian method to test:

public static void main(String[] args) {                                                                                                                               
    ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);

    TestInterface configOfInterface = applicationContext.getBean(MyConfigration.class);
    configOfInterface.hello();    
    configOfInterface.hello();                                                       
    configOfInterface.hello1();                                                            
    configOfInterface.hello1(); 
} 

If add @Configuration(proxyBeanMethods = false) on subclass(SubMyConfigration), will print call hello in super class 3 times.

If add @Configuration on subclass(SubMyConfigration), will print call hello in super class 1 times.

Whether to add @Configuration annotations to the superclass(MyConfigration) and whether to add proxyBeanMethods = false does not affect the number of print times.

According to this part of the code, there are 3 conclusions:

  • subclass(SubMyConfigration) must add @Configuration,otherwise it won't work;
  • No matter whether the superclass adds @Configuration annotations, and whether the proxyBeanMethods = false parameter is added to the annotations, it will not affect the final result.
  • The proxyBeanMethods = false parameter, only added to the subclass @Configuration annotation will affect the result

CodePudding user response:

Maybe I am missing something big here so please feel free to correct me.

@Configuration(proxyBeanMethods = false)
public abstract class AbstractR2dbcConfiguration implements ApplicationContextAware

According to my common sense, an abstract class cannot be registered as a bean even if it has @Configuration.

According to my knowledge @Configuration is never indended to make the annotated class a spring bean. The main reason it exists is that it is a meta information that spring understands so that it can parse it correctly and search the methods that bring @Bean and from those methods it would create spring beans that would be placed inside the spring context.

So even if a class is declared as abstract you don't have any constraint on to define a common method in that abstract class. Then this method could as well be marked with @Bean and that would be no problem for spring to inspect it and use the returned object from that method and place it inside the spring context as a bean.

  • Related