如何在静态初始化之前调用Spring的 @Service方法(在Spring上下文尚未完全加载时)?
我在一个Spring应用中,需要在应用启动阶段非常早地初始化一个 nodeId。
问题在于:
nodeId被用于某些类的 静态块 中。- 其中一个类是
DeploymentConfig。 DeploymentConfig在Spring上下文尚未完全初始化时就被加载。- 因此,无法按常规方式注入Spring bean。
当前实现
在 ApplicationConfig 中我有:
public static String getNodeId() {
if (nodeId == null) {
setNodeId();
}
return nodeId;
}
public static synchronized void setNodeId() {
logger.info("Start setNodeId");
try {
if (nodeId == null) {
nodeId = NodeRegistryHolder.getNodeRegistry().getSerial().toString();
// nodeId = SpringContext.getBean(INodeRegistryService.class)
// .getNodeRegistry().getName();
}
} catch (Throwable e) {
logger.error(e, e);
} finally {
logger.info("End setNodeId, nodeId = {}", nodeId);
}
}
这个方法必须在服务启动时执行,因为许多静态块都依赖它。
必须调用的服务
我需要在这个Spring服务中调用 registerNode():
@Service
public class NodeRegistryServiceImpl implements INodeRegistryService {
@CachePut("node-id")
@Override
public NodeRegistryDTO registerNode() throws BusinessException, DBException {
String IP = GlobalUtil.getMachineIP();
...
NodeRegistry nodeRegistry = nodeRegistryRepository.registerNode(session, IP);
...
return nodeRegistry.getDataTransferObject();
}
}
重要背景:
- IP是动态的(Kubernetes环境),因此必须在运行时注册节点。
- 我们需要一个稳定的逻辑节点标识符。
registerNode()必须在任何使用nodeId的静态块之前被调用。
我尝试过的办法
@DependsOnApplicationContextInitializer- Bean注入
BeanPostProcessor- 手动
SpringContext.getBean(...)
但问题在于顺序:
静态块在Spring完成上下文初始化之前就会执行,因此Bean尚未就绪,值会变成 null。
核心问题
我该如何:
- 在应用启动阶段尽早执行
registerNode() - 让其结果对静态块可用
- 不破坏Spring的生命周期
- 在一个大型遗留项目中,移除静态块不可行
- Java版本为8(尚不能升级),Tomcat版本为8.5。
问题
有哪些符合Spring的正确做法可以:
- 在静态块依赖它之前运行该逻辑?
- 还是正确初始化依赖于Spring管理的bean的静态配置?
在这种场景下,是否存在一个干净的架构解决方案?
解决方案
你是在和Java斗争,而不是和Spring斗争。静态块在Spring上下文创建之前就已经执行。
我似乎只有两个解决方案:
- 将
nodeId的获取和设置移出Spring生态系统。 - 移除对
nodeId的静态依赖。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。