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

Spring如何给静态字段注入值?Oracle数据源配置空指针异常如何解决?

问题根因及解决方案

核心错误点

  • DBCPDataSource类未纳入Spring容器管理,没有加@Component/@Configuration等Spring组件注解,Spring无法扫描到该类,自然不会执行@Value属性注入逻辑。
  • 静态代码块执行时机远早于Spring属性注入:静态代码块在类加载阶段就会执行,此时Spring还未完成Bean的实例化和属性赋值,就算加了组件注解,静态块执行时也拿不到注入后的配置值。
  • 配置值未实际作用于数据源:就算后续@Value成功注入到静态变量,你也没有将注入后的值重新赋值给BasicDataSource实例,数据源使用的还是静态块中硬编码(或者空)的配置。

最小改动修复方案

保留原有工具类写法的前提下,修改代码如下:

package com.pms.pmsapp.util;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class DBCPDataSource {

    private static String URL_STATIC;
    private static String USERNAME_STATIC;
    private static String PASSWORD_STATIC;

    @Value("${spring.datasource.url}")
    public void setUrl(String url){
        DBCPDataSource.URL_STATIC = url;
    }

    @Value("${spring.datasource.username}")
    public void setUsername(String username){
        DBCPDataSource.USERNAME_STATIC = username;
    }

    @Value("${spring.datasource.password}")
    public void setPassword(String password){
        DBCPDataSource.PASSWORD_STATIC = password;
    }

    private static BasicDataSource ds = new BasicDataSource();

    // 替换原来的静态代码块,@PostConstruct会在属性注入完成后执行
    @PostConstruct
    public void initDataSource() {
        ds.setUrl(URL_STATIC);
        ds.setUsername(USERNAME_STATIC);
        ds.setPassword(PASSWORD_STATIC);
        ds.setDriverClassName("oracle.jdbc.OracleDriver");
        ds.setMinIdle(5);
        ds.setMaxIdle(10);
        ds.setMaxOpenPreparedStatements(100);
    }
    
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    
    private DBCPDataSource(){ }
}

注意:需要确保项目启动类的@ComponentScan配置能扫描到DBCPDataSource所在的包,否则Spring还是无法识别该组件。

更符合Spring规范的优化方案

不需要自己封装静态数据源工具类,直接将数据源交给Spring容器管理,使用时直接注入即可:

import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

    @Value("${spring.datasource.url}")
    private String url;
    @Value("${spring.datasource.username}")
    private String username;
    @Value("${spring.datasource.password}")
    private String password;
    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Bean
    public DataSource dataSource() {
        BasicDataSource ds = new BasicDataSource();
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setDriverClassName(driverClassName);
        ds.setMinIdle(5);
        ds.setMaxIdle(10);
        ds.setMaxOpenPreparedStatements(100);
        return ds;
    }
}

需要使用数据库连接的地方直接注入DataSource即可:

@Autowired
private DataSource dataSource;

// 获取连接
Connection conn = dataSource.getConnection();

如果是Spring Boot项目,连上述配置代码都不需要写,只要引入了spring-boot-starter-jdbc和Oracle驱动依赖,Spring Boot会自动根据application.properties里的spring.datasource配置自动创建DataSource Bean,直接注入使用即可。

内容的提问来源于stack exchange,提问作者calai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 08:06:02