You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.7中如何在公共模块读取主模块的application.yml配置属性

Spring Boot 2.7中如何在公共模块读取主模块的application.yml配置属性

看起来你现在遇到的核心问题有两个:一是公共模块缺少Spring上下文相关依赖,导致@Configuration、@Value这些注解用不了;二是你的OurDataSource是手动new出来的,不属于Spring管理的Bean,所以没法自动注入配置。结合你的场景(多个服务模块复用公共数据源逻辑,每个服务要创建7个数据源),我给你整理几个可行的方案:

第一步:先给公共模块补上Spring依赖

你的common-module的pom.xml里没有引入Spring Context相关依赖,所以才会出现package org.springframework.context.annotation does not exist的错误。先在common模块的pom里添加这个依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <!-- 用provided是因为各个服务模块已经引入了这个依赖,避免重复打包 -->
    <scope>provided</scope>
</dependency>

如果你的Spring Boot版本是2.7.x,这个依赖会自动引入对应版本的Spring Context,这样@Configuration、@Value这些注解就能正常使用了。

第二步:把公共数据源逻辑纳入Spring上下文管理

现在你是手动new OurDataSource(),Spring没法给这个类注入配置。我们需要让数据源的配置逻辑被Spring管理,同时读取主模块的application.yml配置。

方案1:用@ConfigurationProperties统一管理Hikari配置(推荐)

这种方式更优雅,后续加新的Hikari配置也不用改多处:

  1. 在公共模块创建Hikari配置属性类:
package com.us.ourapp;

import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Data;

// 用Lombok的@Data自动生成getter/setter,你已经引入了Lombok依赖
@Data
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public class HikariPoolProperties {
    private int minimumIdle;
    private int maximumPoolSize;
}
  1. 在公共模块创建配置类,启用这个属性绑定:
package com.us.ourapp;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(HikariPoolProperties.class)
public class CommonDataSourceConfig {
}
  1. 修改OurDataSource,让它接收Hikari配置参数:
package com.us.ourapp;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Properties;

public class OurDataSource {
    private static final Logger log = LoggerFactory.getLogger(OurDataSource.class);
    private HikariDataSource dataSource;

    public OurDataSource(String url, String user, String password, HikariPoolProperties hikariProps) {
        String jdbcUrl = String.format("jdbc:postgresql://%s", url);
        String[] pieces = url.split("/");
        if (pieces.length < 2) {
            throw new IllegalArgumentException("Invalid DB url format, expected 'server/dbname'");
        }

        Properties props = new Properties();
        props.setProperty("dataSourceClassName", "org.postgresql.ds.PGSimpleDataSource");
        props.setProperty("dataSource.user", user);
        props.setProperty("dataSource.password", password);
        props.setProperty("dataSource.serverName", pieces[0]);
        props.setProperty("dataSource.databaseName", pieces[1]);

        HikariConfig config = new HikariConfig(props);
        config.setMinimumIdle(hikariProps.getMinimumIdle());
        config.setMaximumPoolSize(hikariProps.getMaximumPoolSize());
        this.dataSource = new HikariDataSource(config);

        log.info("DataSource({}, user={}) created minIdle={}, max={}", 
                 jdbcUrl, user, dataSource.getMinimumIdle(), dataSource.getMaximumPoolSize());
    }

    public HikariDataSource getDataSource() {
        return dataSource;
    }
}
  1. 在各个服务模块(比如api-module)创建数据源Bean:
package com.us.ourapp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppDataSourceConfig {
    private final HikariPoolProperties hikariPoolProperties;

    // 自动注入公共模块的Hikari配置属性
    @Autowired
    public AppDataSourceConfig(HikariPoolProperties hikariPoolProperties) {
        this.hikariPoolProperties = hikariPoolProperties;
    }

    // 第一个数据源
    @Bean
    public OurDataSource db1DataSource() {
        return new OurDataSource("db-server-1/user-db", "db-user-1", "db-pass-1", hikariPoolProperties);
    }

    // 第二个数据源,以此类推直到7个
    @Bean
    public OurDataSource db2DataSource() {
        return new OurDataSource("db-server-2/log-db", "db-user-2", "db-pass-2", hikariPoolProperties);
    }
}

方案2:用@Value直接注入配置(简单场景适用)

如果你的Hikari配置不多,也可以直接在公共模块的配置类里用@Value注入:

package com.us.ourapp;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OurDataSourceConfig {
    @Value("${spring.datasource.hikari.minimum-idle}")
    private int hikariMinIdle;

    @Value("${spring.datasource.hikari.maximum-pool-size}")
    private int hikariMaxPoolSize;

    // 提供创建OurDataSource的工厂方法
    public OurDataSource createDataSource(String url, String user, String password) {
        return new OurDataSource(url, user, password, hikariMinIdle, hikariMaxPoolSize);
    }
}

然后修改OurDataSource的构造器,接收这两个参数,后续逻辑和方案1类似。

第三步:确保服务模块能加载到application.yml

你提到application.yml在project-root下,Spring Boot默认不会自动加载这个位置的配置文件。需要在每个服务模块的pom.xml里配置资源复制,把根目录的application.yml复制到服务模块的classpath中:

<build>
    <resources>
        <!-- 先复制根目录的共享配置 -->
        <resource>
            <directory>${project.parent.basedir}/src/main/resources</directory>
        </resource>
        <!-- 再复制服务模块自己的配置(如果有的话) -->
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
</build>

或者,你也可以把共享的application.yml放到common-module/src/main/resources下,这样服务模块依赖common时会自动加载这个配置,不过如果服务模块有自己的配置,会覆盖共享配置的相同属性。

最后要注意的点

  • 确保服务模块的启动类能扫描到公共模块的配置类:比如启动类的@SpringBootApplication加上scanBasePackages = "com.us.ourapp",这样Spring会扫描整个com.us.ourapp包下的所有Spring组件。
  • 如果你用了@ConfigurationProperties,记得在服务模块的启动类上加上@EnableConfigurationProperties,或者公共模块已经用@EnableConfigurationProperties启用了,就不用重复加。

这样改造后,你就不用在每个服务模块里重复传递Hikari的配置参数,所有配置都统一在application.yml里管理,公共模块复用逻辑,也不会有冗余代码啦。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 09:22:58