为什么一些抽象类有Spring@ConfigurationAnnotation?

tsm1rwdh  于 2022-10-04  发布在  Spring
关注(0)|答案(2)|浏览(206)

这是这个问题的一个例子。(Spring-data-r2dbc)

package org.springframework.data.r2dbc.config;

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

根据我的常识,抽象类不能注册为Bean,即使它有@Configuration.由于@Configuration没有@Inherated,因此继承类的对象不会自动注册为Bean,因此我们必须为继承类直接添加@Configuration。我很好奇为什么一些抽象类会有类似上面的代码的@ConfigurationAnnotation。

von4xj4u

von4xj4u1#

我查阅了一些信息,发现抽象类是允许的。

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

Configuration annotation

创作@Configuration类时的约束

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

像这个问题一样,我希望有一些有权势的人可以从源代码的Angular 来解释这个问题。因为除了文档上的说明,我还不知道原因是什么。

我反复测试了一个下午,发现向抽象类添加配置注解似乎没有任何效果,似乎有效的只是最后一个子类上的注解。

以下是代码!首先,我们需要一个接口TestInterface.java

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

然后创建一个抽象类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";                                                                           
    }                                                                                                                                                 
}

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

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

使用mian方法测试:

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(); 
}

如果在子类(SubMyConfigation)上添加@Configuration(proxyBeanMethods = false),将打印call hello in super class 3次。

如果在子类(SubMyConfigation)上添加@Configuration,将打印call hello in super class 1次。

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

根据代码的这一部分,有三个结论:

  • 子类(SubMyConfigration)必须加上@Configuration,否则无效;
  • 无论超类是否添加@Configuration注解,是否在注解中添加proxyBeanMethods = false参数,都不会影响最终结果。
  • proxyBeanMethods = false参数,仅添加到子类@Configuration注解将影响结果
eqfvzcg8

eqfvzcg82#

也许我遗漏了一些重要的东西,所以请随时纠正我。

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

根据我的常识,抽象类不能注册为Bean,即使它有@Configuration.

据我所知,@Configuration从来不会使带注解的类成为一个Spring Bean。它存在的主要原因是,它是一种Spring能够理解的元数据信息,因此它可以正确地解析它并搜索带来@Bean的方法,并从这些方法中创建放置在Spring上下文中的Spring Bean。

因此,即使类被声明为抽象类,在该抽象类中定义公共方法也没有任何约束。然后,此方法也可以标记为@Bean,Spring可以检查它并使用从该方法返回的对象,并将其作为一个Bean放在Spring上下文中。

相关问题