SpringBoot中注入ApplicationContext对象的三种方式

本文介绍在Spring框架中三种获取Bean的方法:直接注入、构造器方法注入及手动构建类实现接口。并通过实例展示了如何使用这些方法,并强调了在使用静态方法前确保Spring加载顺序正确的重要性。

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

在项目中,我们可能需要手动获取spring中的bean对象,这时就需要通过 ApplicationContext 去操作一波了!


1、直接注入(Autowired)

@Component
public class User {

    @Autowired
    private ApplicationContext applicationContext;
}

2、构造器方法注入

@Component
public class User{
    private ApplicationContext applicationContext;

    public User(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
}

3、手动构建类实现接口

/**
 * Spring的ApplicationContext的持有者,可以用静态方法的方式获取spring容器中的bean
 *
 * @author yj
 * @date 2018年5月27日 下午6:32:11
 */
@Component
public class SpringContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        assertApplicationContext();
        return applicationContext;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String beanName) {
        assertApplicationContext();
        return (T) applicationContext.getBean(beanName);
    }

    public static <T> T getBean(Class<T> requiredType) {
        assertApplicationContext();
        return applicationContext.getBean(requiredType);
    }

    private static void assertApplicationContext() {
        if (SpringContextHolder.applicationContext == null) {
            throw new RuntimeException("applicaitonContext属性为null,请检查是否注入了SpringContextHolder!");
        }
    }

}

注:在使用该类静态方法时必须保证spring加载顺序正确!
可以在使用类上添加 @DependsOn(“springContextHolder”),确保在此之前 SpringContextHolder 类已加载!

### SpringBoot 中 WebSocket Mapper 注入失败的原因分析 在 SpringBoot 项目中,WebSocket 的 Bean 是多例的(即每次客户端连接都会创建一个新的 WebSocket 对象),而 Spring 容器中的其他 Bean 默认是单例的。由于 WebSocket 的生命周期是由客户端连接触发的,而不是由 Spring 容器管理的,因此在 WebSocket 初始化时无法直接注入依赖于 Spring 容器管理的 Bean,比如 MyBatis 的 Mapper。 #### 解决方案一:使用 ApplicationContext 获取 Bean 可以利用 `ApplicationContext` 动态获取所需的 Bean。通过这种方式,在 WebSocket 运行期间手动从 Spring 容器中获取 Mapper 或者 Service 层的对象。 以下是具体实现方法: ```java @Component public class MyWebSocketHandler extends TextWebSocketHandler { private final ApplicationContext applicationContext; public MyWebSocketHandler(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 使用 ApplicationContext 手动获取 Mapper UserMapper userMapper = applicationContext.getBean(UserMapper.class); // 调用 Mapper 方法 List<User> users = userMapper.getAllUsers(); System.out.println(users); super.handleTextMessage(session, message); } } ``` 此方式适用于需要动态加载 Bean 场景[^1]。 --- #### 解决方案二:将 WebSocket 配置为单例模式并延迟初始化 如果希望保持 WebSocket 单例模式,则可以在其内部定义一个懒加载机制来处理依赖注入问题。例如,通过代理类或者工厂方法完成对 Mapper 的访问。 下面是一个基于 Factory Pattern 的例子: ```java @Component public class WebSocketFactory { @Autowired private UserMapper userMapper; public UserMapper getUserMapper() { return userMapper; } } @Component public class MyWebSocketHandler extends TextWebSocketHandler { @Autowired private WebSocketFactory webSocketFactory; @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 通过工厂类间接调用 Mapper UserMapper userMapper = webSocketFactory.getUserMapper(); // 查询数据库操作 List<User> users = userMapper.getAllUsers(); System.out.println(users); super.handleTextMessage(session, message); } } ``` 这种方法能够有效分离 WebSocket 和 Mapper 的耦合关系[^2]。 --- #### 解决方案三:调整 WebSocket 生命周期至 Spring 管理范围 另一种思路是让 WebSocket 成为 Spring 容器完全托管的一个组件。这样就可以像普通 Controller 类一样正常注入 Mapper 或服务层逻辑。 修改后的代码如下所示: ```java @Component public class MyWebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myWebSocketHandler(), "/websocket").setAllowedOrigins("*"); } @Bean public WebSocketHandler myWebSocketHandler() { return new MyWebSocketHandler(); } } @Component public class MyWebSocketHandler extends TextWebSocketHandler { @Autowired private UserMapper userMapper; @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 正常调用已注入的 Mapper List<User> users = userMapper.getAllUsers(); System.out.println(users); super.handleTextMessage(session, message); } } ``` 上述配置使得 WebSocket 可以被 Spring 容器统一管理,并支持标准的 DI 模型[^3]。 --- ### 总结 以上三种方法分别针对不同场景提供了灵活的选择: - 如果仅需临时获取某个特定 Bean,推荐 **解决方案一**; - 若涉及复杂业务流程且不希望增加额外依赖,可采用 **解决方案二**; - 若要彻底融入 Spring 生态体系,则应优先考虑 **解决方案三**。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值