如何使用Spring将A类运行时生成的字符串注入到不同包的B类中
解决方案
根据你的项目类型,可选择以下两种通用方案:
方案1:适用于Spring/SpringBoot项目(绝大多数JavaWeb项目使用)
因为你是应用启动时初始化值、用户请求才调用B类,利用Spring的IOC容器管理Bean即可,不需要处理跨包传参的问题:
- 改造A类,交给Spring管理,启动时自动执行初始化逻辑:
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component public class A { private static final Logger LOGGER = LoggerFactory.getLogger(A.class); // 改为私有属性,通过公共方法取值,符合封装规范 private String bitAndSqlExpression; // 注入数据源 private final DataSource dataSource; public A(DataSource dataSource) { this.dataSource = dataSource; } // 项目启动、A类实例化后自动执行该初始化方法 @PostConstruct public void setBitAndSqlExpression() { try { String driverName = dataSource.getConnection().getMetaData().getDriverName(); if (driverName.contains("PostgreSQL")) { bitAndSqlExpression = "%s::INTEGER & %s = %s"; } else { bitAndSqlExpression = "BITAND (%s,%s) = %s"; } } catch (Exception e) { LOGGER.warn("未识别到数据库驱动,位操作相关逻辑会执行异常"); } } // 提供公共取值方法 public String getBitAndSqlExpression() { return bitAndSqlExpression; } }
- 改造B类,直接注入A类的实例取值即可:
import org.springframework.stereotype.Component; @Component public class B { private final String bitAndSqlExpression; // Spring会自动注入不同包下的A类实例,不需要你手动传参 public B(A a) { this.bitAndSqlExpression = a.getBitAndSqlExpression(); } // 你的业务方法直接用该变量即可 public void handleUserRequest() { String executeSql = String.format(bitAndSqlExpression, "字段名", "参数1", "参数2"); // 后续执行SQL逻辑 } }
如果你不想在B类中引入A类的依赖,也可以直接把SQL表达式注册为独立的Bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration public class SqlConfig { @Bean public String bitAndSqlExpression(DataSource dataSource) throws Exception { String driverName = dataSource.getConnection().getMetaData().getDriverName(); if (driverName.contains("PostgreSQL")) { return "%s::INTEGER & %s = %s"; } return "BITAND (%s,%s) = %s"; } }
之后B类直接注入这个字符串Bean即可:
public class B { private final String bitAndSqlExpression; public B(String bitAndSqlExpression) { this.bitAndSqlExpression = bitAndSqlExpression; } }
方案2:适用于无IOC容器的普通Java项目
用单例模式管理A类的实例,全局唯一,B类直接获取单例取值即可:
- 改造A类为懒汉单例:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.sql.DataSource; public class A { private static final Logger LOGGER = LoggerFactory.getLogger(A.class); private String bitAndSqlExpression; private DataSource dataSource; // 单例实例 private static volatile A INSTANCE; private A() {} // 应用启动时调用一次该方法完成初始化 public static void init(DataSource dataSource) { if (INSTANCE == null) { synchronized (A.class) { if (INSTANCE == null) { INSTANCE = new A(); INSTANCE.dataSource = dataSource; INSTANCE.setBitAndSqlExpression(); } } } } // 提供全局获取单例的方法 public static A getInstance() { if (INSTANCE == null) { throw new RuntimeException("A类未初始化,请先调用init方法"); } return INSTANCE; } private void setBitAndSqlExpression() { try { String driverName = dataSource.getConnection().getMetaData().getDriverName(); if (driverName.contains("PostgreSQL")) { bitAndSqlExpression = "%s::INTEGER & %s = %s"; } else { bitAndSqlExpression = "BITAND (%s,%s) = %s"; } } catch (Exception e) { LOGGER.warn("未识别到数据库驱动,位操作相关逻辑会执行异常"); } } public String getBitAndSqlExpression() { return bitAndSqlExpression; } }
- B类直接调用单例取值,不需要构造传参:
public class B { public void handleUserRequest() { String bitAndSqlExpression = A.getInstance().getBitAndSqlExpression(); // 后续直接使用该变量即可 } }
注意事项
- 两种方案都满足你的时序要求:启动时完成A类的初始化赋值,用户请求调用B类时已经可以拿到正确值
- Spring Boot 3+版本需要将
@PostConstruct的包替换为jakarta.annotation.PostConstruct
内容的提问来源于stack exchange,提问作者yed2393
相关产品推荐
相关产品推荐

