为什么某些抽象类有spring@Configuration注释



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

package org.springframework.data.r2dbc.config;
@Configuration(proxyBeanMethods = false)
public abstract class AbstractR2dbcConfiguration implements ApplicationContextAware {
...
}

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

我查找了一些信息,发现允许使用抽象类。

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

配置注释

创作@Configuration类时的约束

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

就像这个问题一样,我希望有一些强大的家伙可以从源代码的角度解释这个问题。因为除了文档中的说明之外,我还不知道原因是什么。


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

这是密码!!!首先,我们需要一个接口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";                                         
}                                                                           
}  

使用主要方法进行测试:

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

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

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

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

根据这部分代码,有3个结论:

  • 子类(SubMyConfigration(必须添加@Configuration,否则将不起作用
  • 无论超类是否添加了@Configuration注释,以及proxyBeanMethods = false参数是否添加到注释中,都不会影响最终结果
  • 仅添加到子类@Configuration注释的proxyBeanMethods = false参数将影响结果

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

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

根据我的常识,抽象类是不能注册的作为bean,即使它有@Configuration。

据我所知,@Configuration从未被要求使带注释的类成为springbean。它存在的主要原因是,它是spring能够理解的元信息,因此它可以正确地解析它并搜索产生@Bean的方法,并从这些方法中创建将被放置在spring上下文中的springbean。

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

最新更新