主要封装一些获取 bean 的方法,代码如下:
@Component
public class SpringUtils implements ApplicationContextAware {
/**
* 上下文对象实例
*/
private static ApplicationContext context = null;
@Override
@Autowired
public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
log.info("Inject applicationContext succeeded");
}
public static ApplicationContext getApplicationContext() {
if (context == null) {
throw new IllegalArgumentException("ApplicationContext wasn't injected");
}
return context;
}
}
在其他 bean 的构造方法里面调用SpringUtils.getApplicationContext
。
奇怪的是,在 idea 启动正常,打包部署的时候就会抛错IllegalArgumentException
。
网上一推解法都试过了,都没用。 请求大佬支援。
1
agzou 2022-06-15 18:19:57 +08:00
|
2
fzdwx 2022-06-15 18:20:58 +08:00
没问题
|
3
justRua 2022-06-15 19:53:28 +08:00
本地 debug 可以但是打包后不行,可能是打的包有问题,可以远程 debug 看看启动时会不会进 setApplicationContext
|
4
Red998 2022-06-15 20:04:56 +08:00
SpringUtils. context= applicationContext; 需要指向
不需要 @Autowired 这个 spring 生命周期会回调接口 |
5
fmumu 2022-06-15 20:15:50 +08:00
1 是 ApplicationContextAware 的的调用和 bean 的初始化先后问题
2 是在其他 bean 的初始化为什么要用这个 utils,依赖其他 bean 的话用构造器注入不就好了 |
6
BBCCBB 2022-06-15 20:24:00 +08:00
你是不是在这个 setApplicationContext 方法完成之前就调用了 getApplicationContext? 还有就是实现接口的方法上不需要加 @Autowired
|
7
zhongpingjing OP |
8
zhongpingjing OP @BBCCBB 我在其他 bean 的构造方法调了,可能这个 bean 比 SpringUtils 先加载?
|
9
agzou 2022-06-16 09:34:59 +08:00
@zhongpingjing #8 调用的 bean 应该在初始完之后调用,实现 InitializingBean 接口 afterPropertiesSet 方法,或者使用 @PostConstruct ,在构造方法里面不能保证其他 bean 给初始化了
|
10
zhongpingjing OP |
11
zhongpingjing OP @agzou 目前是打算按你这样说改造了,如果这个问题找不到原因的话
|
12
zhongpingjing OP @justRua 会进的,不在其他 bean 里面调用 getApplicationContext ,最后能打印 Inject applicationContext succeeded 。感觉是调用顺序问题,就是 idea 启动 utils 能在其他 bean 先加载,打包后就反了
|
13
BBCCBB 2022-06-16 09:58:38 +08:00
> 我在其他 bean 的构造方法调了
你在构造方法里调用这个? bean 加载的顺序不固定. 你可以试试 @DependsOn 或者在其他 bean 里监听 @ApplicationReadyEvent 来做初始化. @Order 对 bean 的加载没用, 只对 interceptor 这些 aop 有用. |
14
cppc 2022-06-16 10:30:30 +08:00
@zhongpingjing order 不是这样用的哦。你要想"要求" SpringUtils 在初始化(构造方法)时必须可用,最简单的方法就是在构造方法中添加一个 SpringUtils 类型参数,这样 Spring 就知道依赖关系了。
```java @Service public class MyService { // 如果要确保在 bean 初始化期间用到另一个 bean public MyService (SpringUtils utils){ assert utils != null; } // 你自己能确认 SpringUtils 已经初始化的情况下,才能直接使用,比如应用已经启动了 @EventListener public void doIt(ApplicationStartedEvent evt){ assert SpringUtils.getApplicationContext() != null; } } ``` 总之,要么你自己确保依赖关系正确,要么给 Spring 足够的提示,让他帮你管理。 |
15
zhongpingjing OP |
16
zhongpingjing OP @cppc 嗯嗯,确实是顺序问题,把依赖顺序明确了后就行了,神奇的地方就是 idea 启动正常,打包启动就不正常
|
17
BBCCBB 2022-06-16 10:48:05 +08:00
不建议这样用哈, 启动阶段依赖 applicationContext 的地方, 采用注入 ApplicationContext 字段, 在 afterPropertiesSet 里执行初始化, 启动完成后可以用你这个工具类.
|