为什么有些抽象类有 spring @Configuration 注解?

blu*_*ope 5 java spring spring-data-r2dbc

这是这个问题的一个例子。(弹簧数据-r2dbc)

package org.springframework.data.r2dbc.config;

@Configuration(proxyBeanMethods = false)
public abstract class AbstractR2dbcConfiguration implements ApplicationContextAware {
...
}
Run Code Online (Sandbox Code Playgroud)

按照我的常识,抽象类即使有@Configuration,也不能注册为bean。并且由于@Configuration没有@Inherited,所以继承类的对象不会自动注册为bean,所以我们必须直接为继承类添加@Configuration。我很好奇为什么有些抽象类有 @Configuration 注解,就像上面的代码一样。

ala*_*ala 3

我查了一些资料,发现抽象类是允许的。

\n

文档中的约束并没有说抽象类或接口(可以?)不支持配置注释。

\n

配置注解

\n

创作 @Configuration 类时的约束

\n
    \n
  • 配置类必须作为类提供(即不是作为从工厂方法返回的实例),从而允许通过生成的子类进行运行时增强。
  • \n
  • 配置类必须是非最终的(允许在运行时生成子类),除非 proxyBeanMethods 标志设置为 false,在这种情况下,不需要运行时生成的子类。
  • \n
  • 配置类必须是非本地的(即不能在方法内声明)。
  • \n
  • 任何嵌套配置类都必须声明为静态。
  • \n
  • @Bean 方法可能不会依次创建进一步的配置类(任何此类实例都将被视为常规 bean,其配置注释仍然未被检测到)。
  • \n
\n

像这个问题,希望有强者能从源码的角度解释一下这个问题。\n因为除了文档中的说明,我还不知道原因是什么。

\n
\n

反复测试了一下午,发现在抽象类上添加Configuration注解似乎没有任何效果,看起来有效的只是最终子类上的注解。

\n

这是代码!!!\n首先,我们需要一个接口TestInterface.java

\n
public interface TestInterface {                                                                         \n    public String hello();                                                                                         \n    public String hello1();                                                                                        \n}   \n
Run Code Online (Sandbox Code Playgroud)\n

然后创建一个抽象类MyConfigration.java

\n
//@Configuration(proxyBeanMethods = false)\n//@Configuration\npublic abstract class MyConfigration implements TestInterface  {      \n    @Bean                                                                       \n    public String hello() {                                                     \n        System.out.println("call hello in super class");                        \n        return "hello";                                                                           \n    }                                                                                                                                                 \n}\n
Run Code Online (Sandbox Code Playgroud)\n

最后,我们需要一个子类SubMyConfigration.java

\n
@Configuration                                                                  \nclass SubMyConfigration extends MyConfigration {                              \n    @Bean                                                                       \n    public String hello1() {                                                    \n        return " hello1 from subclass";                                         \n    }                                                                           \n}  \n
Run Code Online (Sandbox Code Playgroud)\n

使用main方法测试:

\n
public static void main(String[] args) {                                                                                                                               \n    ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);\n\n    TestInterface configOfInterface = applicationContext.getBean(MyConfigration.class);\n    configOfInterface.hello();    \n    configOfInterface.hello();                                                       \n    configOfInterface.hello1();                                                            \n    configOfInterface.hello1(); \n} \n
Run Code Online (Sandbox Code Playgroud)\n

如果添加@Configuration(proxyBeanMethods = false)子类(SubMyConfigration),将打印call hello in super class3次。

\n

如果添加@Configuration子类(SubMyConfigration),将打印call hello in super class1次。

\n

@Configuration超类(MyConfigration)是否添加注解以及是否添加proxyBeanMethods = false不影响打印次数。

\n

根据这部分代码,有3个结论\xef\xbc\x9a

\n
    \n
  • subclass( SubMyConfigration)必须添加@Configuration,否则不起作用;
  • \n
  • 无论超类是否添加@Configuration注解,以及proxyBeanMethods = false注解中是否添加参数,都不会影响最终的结果。
  • \n
  • proxyBeanMethods = false参数,只有添加到子类@Configuration注解中才会影响结果
  • \n
\n