Boosting Dubbo Performance with Spring Boot Auto‑Configuration and a Multi‑Data‑Source SDK

The article details how a high‑frequency Dubbo call bottleneck was resolved by creating a conditional Spring Boot auto‑configuration multi‑data‑source SDK that dynamically loads beans, avoids bean conflicts, and enables direct database access, dramatically reducing latency and system load.

Java Companion
Java Companion
Java Companion
Boosting Dubbo Performance with Spring Boot Auto‑Configuration and a Multi‑Data‑Source SDK

Problem: Dubbo performance bottleneck

In a large micro‑service project, high‑frequency data‑query operations were invoked via Dubbo. Under high concurrency the latency became noticeable, and the Dubbo service could not be horizontally scaled because of database constraints.

Solution: Conditional auto‑configuration multi‑data‑source SDK

Project structure

sdk-multi-datasource/
├── src/main/java/com/example/sdk/
│   ├── config/
│   │   ├── condition/AnySdkDataSourceCondition.java
│   │   ├── datasource/SdkPrimaryDataConfig.java
│   │   ├── datasource/SdkSecondaryDataConfig.java
│   │   └── SdkAutoConfiguration.java
│   ├── dao/primary/SdkAppInfoDao.java
│   ├── dao/secondary/SdkOtherDataDao.java
│   ├── service/SdkAppInfoService.java
│   ├── service/SdkOtherDataService.java
│   └── ...
├── src/main/resources/META-INF/spring.factories
└── pom.xml

Conditional class: detecting data‑source configuration

public class AnySdkDataSourceCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment env = context.getEnvironment();
        return env.containsProperty("spring.datasource.sdk-primary.jdbc-url") ||
               env.containsProperty("spring.datasource.sdk-secondary.jdbc-url");
    }
}

Primary data‑source configuration

@Configuration
@ConditionalOnProperty(prefix = "spring.datasource.sdk-primary", name = "jdbc-url")
@MapperScan(basePackages = "com.example.sdk.dao.primary", sqlSessionFactoryRef = "sdkPrimarySqlSessionFactory")
public class SdkPrimaryDataConfig {
    @Bean(name = "sdkPrimaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.sdk-primary")
    public DataSource sdkPrimaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "sdkPrimarySqlSessionFactory")
    public SqlSessionFactory sdkPrimarySqlSessionFactory(@Qualifier("sdkPrimaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mapper/primary/*.xml"));
        return bean.getObject();
    }

    @Bean(name = "sdkPrimarySqlSessionTemplate")
    public SqlSessionTemplate sdkPrimarySqlSessionTemplate(@Qualifier("sdkPrimarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "sdkPrimaryTransactionManager")
    public DataSourceTransactionManager sdkPrimaryTransactionManager(@Qualifier("sdkPrimaryDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

Secondary data‑source configuration

The secondary configuration mirrors the primary one, with bean names, package paths, and property prefixes changed from primary to secondary.

DAO layer interfaces

@Mapper
public interface SdkAppInfoDao {
    AppInfo getByBusinessId(String businessId);
}

Service layer implementation

public class SdkAppInfoService {
    private SdkAppInfoDao sdkAppInfoDao;

    public void setSdkAppInfoDao(SdkAppInfoDao dao) { this.sdkAppInfoDao = dao; }

    public AppInfo getByBusinessId(String businessId) {
        return sdkAppInfoDao.getByBusinessId(businessId);
    }
}

Auto‑configuration class

@Configuration
@Conditional(AnySdkDataSourceCondition.class)
@Import({SdkPrimaryDataConfig.class, SdkSecondaryDataConfig.class})
public class SdkAutoConfiguration {
    @Bean @Lazy @ConditionalOnProperty(prefix = "spring.datasource.sdk-primary", name = "jdbc-url")
    public SdkAppInfoService sdkAppInfoService(SdkAppInfoDao dao) {
        SdkAppInfoService service = new SdkAppInfoService();
        service.setSdkAppInfoDao(dao);
        return service;
    }

    @Bean @Lazy @ConditionalOnProperty(prefix = "spring.datasource.sdk-secondary", name = "jdbc-url")
    public SdkOtherDataService sdkOtherDataService(SdkOtherDataDao dao) {
        SdkOtherDataService service = new SdkOtherDataService();
        service.setSdkOtherDataDao(dao);
        return service;
    }
}

Registration in spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.sdk.config.SdkAutoConfiguration

Consumer usage

Add the SDK as a Maven dependency and configure the desired data sources following Spring Boot conventions.

<dependency>
    <groupId>com.example</groupId>
    <artifactId>sdk-multi-datasource</artifactId>
    <version>1.0.0</version>
</dependency>
spring:
  datasource:
    sdk-primary:
      jdbc-url: jdbc:mysql://primary-db-host:3306/primary_db
      username: db_user
      password: db_password
      driver-class-name: com.mysql.jdbc.Driver
    sdk-secondary:
      jdbc-url: jdbc:mysql://secondary-db-host:3306/secondary_db
      username: db_user
      password: db_password
      driver-class-name: com.mysql.jdbc.Driver

Inject the SDK service directly in a controller.

@RestController
public class BusinessController {
    @Autowired
    private SdkAppInfoService sdkAppInfoService;

    @GetMapping("/app-info/{businessId}")
    public AppInfo getAppInfo(@PathVariable String businessId) {
        return sdkAppInfoService.getByBusinessId(businessId);
    }
}

Result and analysis

Replacing high‑frequency Dubbo calls with local database connections via the SDK significantly lowered latency and system load. The conditional annotations ensure that beans are created only when the corresponding data source is configured, preventing unnecessary bean loading, memory waste, and runtime errors.

On‑demand loading : Beans are instantiated only after the related data source property is present.

Conflict avoidance : All SDK beans are prefixed with "Sdk", eliminating name clashes with existing beans.

Flexible configuration : Teams can enable any combination of primary and secondary data sources.

@Lazy effect : Service beans are lazily initialized, guaranteeing that their DAO dependencies are already available when the service is first used.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DubboSpring Bootauto-configurationlazy-initializationMulti-DataSourceConditional Bean
Java Companion
Written by

Java Companion

A highly professional Java public account

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.