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
相关产品推荐
相关产品推荐

