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
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 theproxyBeanMethods = 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.