SpringBoot自动装配子属性时如何继承父级配置属性?
问题描述
我有一个Java SpringBoot应用,application.yaml配置如下,其中timeOut和retryCount是myEventhub1与someEventHub的公共属性:
azure: eventhub: timeOut: ${timeOut} retryCount: ${retryCount} myEventhub1: eventhubName: ${myEventhubName} sasKeyName: ${myEventhubKeyName} sasKeyValue: ${myEventhubKey} someEventHub: eventhubName: ${someEventhubName} sasKeyName: ${someEventhubKeyName} sasKeyValue: ${someEventhubKey}
第三方库提供了无法修改的类:
public class EventhubSettings { private String eventhubName; private String sasKeyName; private String sasKeyValue; private int retryCount; private int timeOut; // 第三方类自带getter/setter方法 }
自定义配置类如下:
@Getter @Setter @Configuration @ConfigurationProperties("azure.eventhub") public class MyEventhubConfig { private EventhubSettings myEventhub1; private EventhubSettings someEventHub; }
需要实现MyEventhubConfig中的myEventhub1和someEventHub自动继承父级azure.eventhub下的retryCount和timeOut属性,避免在子节点下重复配置这两个属性。
解决方案
方法1:配置类初始化时手动填充公共属性
修改MyEventhubConfig,新增父级公共属性的字段,通过@PostConstruct在配置初始化后,将父级属性填充到子配置对象中(保留子节点单独配置的优先级):
@Getter @Setter @Configuration @ConfigurationProperties("azure.eventhub") public class MyEventhubConfig { // 父级公共属性 private int timeOut; private int retryCount; private EventhubSettings myEventhub1; private EventhubSettings someEventHub; @PostConstruct public void fillCommonProperties() { // 为myEventhub1填充公共属性 if (myEventhub1 != null) { if (myEventhub1.getRetryCount() == 0) { // 根据第三方类默认值调整判断逻辑 myEventhub1.setRetryCount(retryCount); } if (myEventhub1.getTimeOut() == 0) { myEventhub1.setTimeOut(timeOut); } } // 为someEventHub填充公共属性 if (someEventHub != null) { if (someEventHub.getRetryCount() == 0) { someEventHub.setRetryCount(retryCount); } if (someEventHub.getTimeOut() == 0) { someEventHub.setTimeOut(timeOut); } } } }
方法2:YAML锚点复用公共配置
无需修改Java代码,直接在application.yaml中使用YAML的锚点和合并语法,复用公共属性:
azure: eventhub: &commonProps timeOut: ${timeOut} retryCount: ${retryCount} myEventhub1: <<: *commonProps eventhubName: ${myEventhubName} sasKeyName: ${myEventhubKeyName} sasKeyValue: ${myEventhubKey} someEventHub: <<: *commonProps eventhubName: ${someEventhubName} sasKeyName: ${someEventhubKeyName} sasKeyValue: ${someEventhubKey}
&commonProps定义公共属性锚点,<<: *commonProps将锚点属性合并到当前子节点,子节点也可以单独覆盖timeOut或retryCount实现个性化配置。
方法3:自定义Bean后置处理器(批量处理场景)
如果有多个类似配置需要处理,可自定义BeanPostProcessor,在配置类初始化后自动填充公共属性:
@Component public class EventhubSettingsBindingPostProcessor implements BeanPostProcessor { @Autowired private Environment environment; @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof MyEventhubConfig) { MyEventhubConfig config = (MyEventhubConfig) bean; // 从环境中读取父级公共属性 int timeOut = environment.getProperty("azure.eventhub.timeOut", Integer.class, 0); int retryCount = environment.getProperty("azure.eventhub.retryCount", Integer.class, 0); fillSettings(config.getMyEventhub1(), timeOut, retryCount); fillSettings(config.getSomeEventHub(), timeOut, retryCount); } return bean; } private void fillSettings(EventhubSettings settings, int timeOut, int retryCount) { if (settings == null) return; if (settings.getRetryCount() == 0) { settings.setRetryCount(retryCount); } if (settings.getTimeOut() == 0) { settings.setTimeOut(timeOut); } } }
内容的提问来源于stack exchange,提问作者user29454562
相关产品推荐
相关产品推荐

