为什么 Spring @Configuration class 继承没有按预期工作?
Why is Spring @Configuration class inheritance not working as expected?
我有一个抽象 Spring 配置 class,其中包含一个公共 bean:
public abstract class AbstractConfig {
@Bean
public CommonBean commonBean {
CommonBean commonBean = new CommonBean();
commonBean.specifics = getSpecifics();
};
public abstract String getSpecifics();
}
公共 bean 的细节由其子classes 设置:
package realPackage;
@Configuration
public class RealConfig extends AbstractConfig {
@Override
public String getSpecifics() {
return "real";
}
}
...和...
package testPackage;
@Configuration
@ComponentScan(basePackages = {"testPackage", "realPackage" })
public class TestConfig extends AbstractConfig {
@Override
public String getSpecifics() {
return "test";
}
}
我的测试只需要使用 TestConfig
,不应该知道 RealConfig
(但确实需要访问 realPackage
中的其他组件)。开始:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class MyIntegrationTestIT { //... }
使用上面的代码,这会按预期工作并使用 "test"
细节。但是,如果我颠倒 @ComponentScan
中包的顺序,则会使用 "real"
细节。这让我感到困惑 - 我指定了 TestConfig
所以它肯定应该调用覆盖的方法吗?谁能告诉我 Spring 这样做的原因以及如何解决这个问题?
您当前的示例很可能无法编译。 AbstractConfig 应该看起来像这个代码片段,但我认为这只是一个 copy/paste 错误。
public abstract class AbstractConfig {
@Bean
public CommonBean commonBean() {
CommonBean commonBean = new CommonBean();
commonBean.specifics = getSpecifics();
return commonBean;
}
public abstract String getSpecifics();
}
您正在查找的功能是@Profile 注释(有关详细信息,请参阅https://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile)。您需要按如下方式更改您的代码
RealConfig
package realPackage;
@Configuration
@Profile("real")
public class RealConfig extends AbstractConfig {
...
测试配置
package testPackage;
@Configuration
@ComponentScan(basePackages = {"testPackage", "realPackage" })
@Profile("test")
public class TestConfig extends AbstractConfig {
MyIntegrationTestIT
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@ActiveProfiles("test")
public class MyIntegrationTestIT {
...
问题原来是由于我对组件扫描如何拾取带有 @Configuration
注释的 bean 缺乏理解。
我有一个抽象 Spring 配置 class,其中包含一个公共 bean:
public abstract class AbstractConfig {
@Bean
public CommonBean commonBean {
CommonBean commonBean = new CommonBean();
commonBean.specifics = getSpecifics();
};
public abstract String getSpecifics();
}
公共 bean 的细节由其子classes 设置:
package realPackage;
@Configuration
public class RealConfig extends AbstractConfig {
@Override
public String getSpecifics() {
return "real";
}
}
...和...
package testPackage;
@Configuration
@ComponentScan(basePackages = {"testPackage", "realPackage" })
public class TestConfig extends AbstractConfig {
@Override
public String getSpecifics() {
return "test";
}
}
我的测试只需要使用 TestConfig
,不应该知道 RealConfig
(但确实需要访问 realPackage
中的其他组件)。开始:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class MyIntegrationTestIT { //... }
使用上面的代码,这会按预期工作并使用 "test"
细节。但是,如果我颠倒 @ComponentScan
中包的顺序,则会使用 "real"
细节。这让我感到困惑 - 我指定了 TestConfig
所以它肯定应该调用覆盖的方法吗?谁能告诉我 Spring 这样做的原因以及如何解决这个问题?
您当前的示例很可能无法编译。 AbstractConfig 应该看起来像这个代码片段,但我认为这只是一个 copy/paste 错误。
public abstract class AbstractConfig {
@Bean
public CommonBean commonBean() {
CommonBean commonBean = new CommonBean();
commonBean.specifics = getSpecifics();
return commonBean;
}
public abstract String getSpecifics();
}
您正在查找的功能是@Profile 注释(有关详细信息,请参阅https://spring.io/blog/2011/02/14/spring-3-1-m1-introducing-profile)。您需要按如下方式更改您的代码
RealConfig
package realPackage;
@Configuration
@Profile("real")
public class RealConfig extends AbstractConfig {
...
测试配置
package testPackage;
@Configuration
@ComponentScan(basePackages = {"testPackage", "realPackage" })
@Profile("test")
public class TestConfig extends AbstractConfig {
MyIntegrationTestIT
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@ActiveProfiles("test")
public class MyIntegrationTestIT {
...
问题原来是由于我对组件扫描如何拾取带有 @Configuration
注释的 bean 缺乏理解。