目录
前言:在开发过程中,当在静态方法内调用bean的时候会遇到以下类型错误,均是使用不当造成的
ps:不看错误可以直接跳转标题“SpringBoot中的静态方法获取bean的三种方案”
错误1:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderDetailInfoController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderDetailServiceFactory': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'WJOrderDetailService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shopInfoHelper': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wareInfoHelper': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wareButtonHelper' defined in URL [jar:file:xxx/WEB-INF/lib/xxx-1.0-SNAPSHOT.jar!/com/xxx/mti/order/web/service/helpers/ware/WareButtonHelper.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: @Resource annotation is not supported on static fields
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:324) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
原因:提示“@Resource annotation is not supported on static fields”,这个错误是因为在Java中,@Resource注解不支持用在静态字段上。@Resource注解通常用于依赖注入,而不支持用在静态字段上。
错误2:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderDetailInfoController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'orderDetailServiceFactory': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'WJOrderDetailService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'shopInfoHelper': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wareInfoHelper': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wareButtonHelper': Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:324) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
原因:由于 @Resource注解不支持用在静态变量上,便尝试使用@Autowired注解来实现bean注入,缺发现在Springframework
里,我们不能@Autowired一个静态变量,使之成为一个Spring bean,从而出现NPE(java.lang.NullPointerException: null异常)异常。因为当类加载器加载静态变量时,Spring上下文尚未加载。所以类加载器不会在bean中正确注入静态类,并且会失败。
那么如何在springboot的静态方法使用bean呢?以下提供三种解决方案
SpringBoot中的静态方法获取bean的三种方案
方式一 注解@PostConstruct
方式二 启动类ApplicationContext
方式三 手动注入ApplicationContext
方式一 注解@PostConstruct
@Componetn
public class ASerivce {
@Resource
private ConfigService configService;
private static ConfigService staticConfigService;
@PostConstruct
public void init(){
staticConfigService = configService;
}
public static void test(){
staticConfigService.xxx();//等同于configService.xxx()
}
}
注解@PostConstruct说明:
@PostConstruct
注解用于在对象初始化之后执行特定的初始化操作。这个注解通常与依赖注入框架(如Spring)一起使用,以确保在依赖注入完成后立即执行初始化逻辑。适用场景包括:
- 执行需要依赖注入完成后才能进行的初始化逻辑。
- 在对象创建后进行一些必要的设置或准备工作。
例如,在使用Spring框架时,可以在一个方法上添加
@PostConstruct
注解,以确保在依赖注入完成后执行特定的初始化逻辑,如数据加载、资源分配等操作。
注:使用PostConstruct需要执行以下标准
- 该方法不得有任何参数,除非是在 EJB 拦截器 (interceptor) 的情况下,根据 EJB 规范的定义,在这种情况下它将带有一个 InvocationContext 对象 ;
- 该方法的返回类型必须为 void;
- 该方法不得抛出已检查异常;
- 应用 PostConstruct 的方法可以是 public、protected、package private 或 private;
- 除了应用程序客户端之外,该方法不能是 static;
- 该方法可以是 final;
- 如果该方法抛出未检查异常,那么不得将类放入服务中,除非是能够处理异常并可从中恢复的 EJB。
方式二 启动类ApplicationContext
实现方式:在springboot的启动类中,定义static变量ApplicationContext,利用容器的getBean方法获得依赖对象
@SpringBootApplication
public class Application {
public static ConfigurableApplicationContext ac;
public static void main(String[] args) {
ac = SpringApplication.run(Application.class, args);
}
}
调用:
@Componetn
public class BSerivce {
public static void test(){
ConfigService configService = Application.ac.getBean(ConfigService.class);
configService.xxx();
}
}
注:Application类就是我们springboot项目的启动类
方式三 手动注入ApplicationContext
优先创建获取bean的工具类
@Component
public class StaticMethodGetBean<T> implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
StaticMethodGetBean.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext != null?applicationContext.getBean(clazz):null;
}
}
调用:
@Componetn
public class CSerivce {
public static void test(){
ConfigService configService = StaticMethodGetBean.getBean(ConfigService.class);
configService.xxx();
}
}
----end----