首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Java 实现SpringContextUtils工具类,手动获取Bean

  • 25-04-25 14:01
  • 4166
  • 6297
blog.csdn.net

SpringContextUtils 工具类实现

下面是一个完整的 Spring 上下文工具类实现,用于从 Spring 容器中获取 Bean。这个工具类考虑了线程安全、性能优化和易用性,并提供了多种获取 Bean 的方式。

完整实现代码

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * Spring 上下文工具类,用于获取容器中的Bean
 * 
 * 功能包括:
 * 1. 获取ApplicationContext
 * 2. 通过名称获取Bean
 * 3. 通过类型获取Bean
 * 4. 通过名称和类型获取Bean
 * 5. 获取指定类型的所有Bean
 * 6. 获取当前环境配置
 */
@Component
public class SpringContextUtils implements ApplicationContextAware {

    /**
     * 静态ApplicationContext
     */
    private static ApplicationContext applicationContext;

    /**
     * 设置ApplicationContext
     */
    @Override
    public void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {
        if (SpringContextUtils.applicationContext == null) {
            SpringContextUtils.applicationContext = applicationContext;
        }
    }

    /**
     * 获取ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        checkApplicationContext();
        return applicationContext;
    }

    /**
     * 通过名称获取Bean
     * @param name Bean名称
     * @return Bean实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 通过类型获取Bean
     * @param clazz Bean类型
     * @return Bean实例
     */
    public static <T> T getBean(Class<T> clazz) {
        checkApplicationContext();
        return applicationContext.getBean(clazz);
    }

    /**
     * 通过名称和类型获取Bean
     * @param name Bean名称
     * @param clazz Bean类型
     * @return Bean实例
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        checkApplicationContext();
        return applicationContext.getBean(name, clazz);
    }

    /**
     * 获取指定类型的所有Bean
     * @param clazz Bean类型
     * @return Bean名称与实例的映射
     */
    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
        checkApplicationContext();
        return applicationContext.getBeansOfType(clazz);
    }

    /**
     * 获取当前环境配置
     * @param key 配置键
     * @return 配置值
     */
    public static String getProperty(String key) {
        checkApplicationContext();
        return applicationContext.getEnvironment().getProperty(key);
    }

    /**
     * 检查ApplicationContext是否已注入
     */
    private static void checkApplicationContext() {
        if (applicationContext == null) {
            throw new IllegalStateException("ApplicationContext未注入,请在Spring配置中定义SpringContextUtils");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

功能说明

1. 核心功能

  • 获取 ApplicationContext:getApplicationContext()
  • 通过名称获取 Bean:getBean(String name)
  • 通过类型获取 Bean:getBean(Class clazz)
  • 通过名称和类型获取 Bean:getBean(String name, Class clazz)
  • 获取指定类型的所有 Bean:getBeansOfType(Class clazz)
  • 获取环境配置:getProperty(String key)

2. 线程安全性

  • 使用静态变量存储 ApplicationContext,保证全局唯一
  • 通过 @Component 注解让 Spring 管理工具类实例
  • 实现 ApplicationContextAware 接口自动注入上下文

3. 异常处理

  • 检查 ApplicationContext 是否已注入,未注入时抛出明确异常
  • 使用 @Nullable 注解标记可为空的参数
  • 添加泛型支持,减少类型转换

使用示例

1. 基本使用

// 获取ApplicationContext
ApplicationContext context = SpringContextUtils.getApplicationContext();

// 通过名称获取Bean
UserService userService = SpringContextUtils.getBean("userService");

// 通过类型获取Bean
UserService userService = SpringContextUtils.getBean(UserService.class);

// 通过名称和类型获取Bean
UserService userService = SpringContextUtils.getBean("userService", UserService.class);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2. 获取所有同类型Bean

// 获取所有实现UserService接口的Bean
Map<String, UserService> userServices = SpringContextUtils.getBeansOfType(UserService.class);

userServices.forEach((name, service) -> {
    System.out.println("Bean名称: " + name + ", 实例: " + service);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3. 获取环境配置

// 获取application.properties/yml中的配置
String appName = SpringContextUtils.getProperty("spring.application.name");
String serverPort = SpringContextUtils.getProperty("server.port");
  • 1
  • 2
  • 3

高级用法

1. 在非Spring管理的类中使用

public class NonSpringClass {
    public void someMethod() {
        // 获取Spring容器中的Bean
        UserRepository repository = SpringContextUtils.getBean(UserRepository.class);
        repository.save(new User());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2. 在静态方法中使用

public class UtilityClass {
    public static void doSomething() {
        // 静态方法中获取Bean
        EmailService emailService = SpringContextUtils.getBean(EmailService.class);
        emailService.send("[email protected]", "Hello");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3. 在JUnit测试中使用

@SpringBootTest
public class UserServiceTest {
    @Test
    public void testGetUser() {
        // 在测试中获取Bean
        UserService userService = SpringContextUtils.getBean(UserService.class);
        User user = userService.getUserById(1L);
        assertNotNull(user);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现原理

  1. ApplicationContextAware 接口:

    • Spring 会在初始化时自动调用 setApplicationContext 方法
    • 将 ApplicationContext 注入到工具类的静态变量中
  2. 静态方法访问:

    • 所有方法都是静态的,方便在任何地方调用
    • 内部检查 ApplicationContext 是否已初始化
  3. 泛型支持:

    • 减少显式类型转换,提高代码安全性
    • 编译器会检查类型是否匹配

注意事项

  1. 初始化时机:

    • 确保 Spring 容器完全初始化后再使用工具类
    • 不要在 Bean 的构造方法中使用,因为此时 Bean 还未完全初始化
  2. 单元测试:

    • 在测试中需要先启动 Spring 上下文
    • 可以使用 @SpringBootTest 注解
  3. 多线程安全:

    • ApplicationContext 是线程安全的
    • 工具类本身不包含可变状态,也是线程安全的
  4. 替代方案:

    • 在 Spring Boot 中可以直接使用依赖注入
    • 这个工具类主要用在无法使用依赖注入的场景

扩展功能

如果需要更多功能,可以扩展以下方法:

/**
 * 获取当前环境profile
 */
public static String[] getActiveProfiles() {
    checkApplicationContext();
    return applicationContext.getEnvironment().getActiveProfiles();
}

/**
 * 判断当前是否是指定环境
 */
public static boolean isProfileActive(String profile) {
    checkApplicationContext();
    String[] activeProfiles = getActiveProfiles();
    return Arrays.asList(activeProfiles).contains(profile);
}

/**
 * 发布事件
 */
public static void publishEvent(Object event) {
    checkApplicationContext();
    applicationContext.publishEvent(event);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

这个 SpringContextUtils 工具类提供了一种简洁的方式来访问 Spring 容器中的 Bean,特别适合在非 Spring 管理的类中获取 Spring Bean 的场景。

注:本文转载自blog.csdn.net的兔子蟹子的文章"https://blog.csdn.net/qq_45351273/article/details/147465909"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top