SpringBoot中的静态方法如何获取bean

本文介绍了在SpringBoot中静态方法获取bean的三种方法:1) 使用@PostConstruct注解;2) 在启动类中定义静态ApplicationContext;3) 创建获取bean的工具类并手动注入ApplicationContext。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

SpringBoot中的静态方法获取bean的三种方案

方式一 注解@PostConstruct

方式二 启动类ApplicationContext

方式三 手动注入ApplicationContext


前言:在开发过程中,当在静态方法内调用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)一起使用,以确保在依赖注入完成后立即执行初始化逻辑。

适用场景包括:

  1. 执行需要依赖注入完成后才能进行的初始化逻辑。
  2. 在对象创建后进行一些必要的设置或准备工作。

例如,在使用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----

### Spring Boot 中静态属性、静态方法以及 Bean 的生命周期 #### 静态属性和静态方法的作用 在 Java 类中,静态属性和静态方法属于类本身而非实例对象。这意味着这些成员可以在不创建类的具体实例的情况下被访问。对于静态属性,在整个应用程序运行期间只会存在一份副本;而对于静态方法,则可以直接通过类名调用来执行。 当涉及到 Spring 应用程序上下文中时,如果某个 Bean 或者其内部组件依赖于静态资源(如静态变量或方法),需要注意初始化顺序和服务提供方式: - **静态属性**:通常用于存储常量或其他在整个应用范围内共享的数据。 - **静态方法**:可以作为工具函数来使用,尤其是在不需要特定实例状态的操作场景下非常有用。 然而,由于 Spring 主要基于面向对象的设计模式工作,因此建议尽可能减少对静态特性的过度依赖,转而采用更灵活的注入机制[^1]。 #### Bean 生命周期概述 Spring 容器中的每一个 Bean 实例都会经历一系列预定义的状态转换过程——即所谓的“生命周期”。这个过程中包含了多个阶段,允许开发者自定义某些行为以满足业务需求。具体来说,典型的 Bean 生命周期如下所示: 1. **实例化 (Instantiation)** 当容器接收到关于某类型的 Bean 创建请求后,会先利用反射技术构建该类型的新实例。 2. **属性赋值 (Populate Properties)** 接下来设置由 XML 文件或者其他形式配置文件所指定的各种属性值给新生成的对象。 3. **Aware 方法调用** 4. **初始化前处理 (@PostConstruct / InitializingBean)** 如果实现了 `InitializingBean` 接口或是标注有 `@PostConstruct` 注解的方法将会在此刻被执行。 5. **初始化完成 (Initialization Callbacks)** 此处可以通过实现 Lifecycle 接口参与容器级别的启动/停止事件监听逻辑。 6. **可用状态** 7. **销毁前清理 (@PreDestroy / DisposableBean)** 对于单例作用域之外的情况(比如原型 Prototype 范围内的 Beans),一旦不再需要就会触发此步骤来进行必要的释放操作。不过值得注意的是,对于原型 BeanSpring 并不会自动管理它们完整的生命周期,也就意味着框架不会主动去调用任何已配置好的销毁回调函数[^2]。 8. **完全清除** 下面是一个简单的例子展示了如何在一个普通的 Service 组件里加入上述提到的一些特性: ```java import org.springframework.beans.factory.DisposableBean; import org.springframework.context.annotation.Scope; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; public class MyService implements DisposableBean { private static final String STATIC_PROPERTY = "This is a static property"; @PostConstruct public void init() { System.out.println("MyService initialized."); } public void doStuff(){ // Some business logic here... System.out.println(STATIC_PROPERTY); } @Override @PreDestroy public void destroy() throws Exception { System.out.println("MyService destroyed."); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值