@SpringContext通过实现ApplicationContextAware接口动态获取bean

场景:

在代码中需要动态获取spring管理的bean

目前遇到的主要有两种场景:
1.在工具类中需要调用某一个Service完成某一个功能,如DictUtils
2.在实现了Runnable接口的任务类中需要调用某一个Service完成run方法中的功能!

代码:

SpringContextUtils.java

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

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextUtils.applicationContext = applicationContext;
        System.out.println("spring容器在项目构建的时候就执行了");
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            //beanDefinitionName是容器中bean实例的id
            //<bean id="">对应此处的id
            System.out.println(beanDefinitionName);
        }
    }

    /**
     * 当通过接口多个实现时,需要用 beanName区分
     *
     * @param name 注册的 bean名称
     * @param clazz 注册的 bean类型
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        if (applicationContext == null){
            return null;
        }
        return applicationContext.getBean(name, clazz);
    }

    /***
     * 根据一个bean的类型获取配置文件中相应的bean
     */
    public static <T> T getBeanByClass(Class<T> requiredType) {
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(requiredType);
    }

    public static ApplicationContext getApplicationContext() {
        return ApplicationContextUtils.applicationContext;
    }
}

控制台输出

spring容器在项目构建的时候就执行了

sqlSessionFactory
org.mybatis.spring.mapper.MapperScannerConfigurer#0
dataSource
org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0
transactionManager
org.springframework.aop.config.internalAutoProxyCreator
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0
org.springframework.transaction.interceptor.TransactionInterceptor#0
org.springframework.transaction.config.internalTransactionAdvisor
myTbItemServiceImpl
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
springContext
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
tbItemMapper
@Service("myTbItemServiceImpl")
public class TbItemServiceImpl implements ITbItemService

这几个注解所在的包是

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.2.5.RELEASE</version>
</dependency>

SpringContextUtils必须放在Spring容器中

要么在xml配置文件中声明,要么加上注解

<think>好的,我需要回答用户关于Spring的ApplicationContextAware接口的原理和作用的问题。首先,我得回顾一下相关的知识,确保自己理解正确。 用户的问题是,为什么实现ApplicationContextAware接口可以让Bean访问到ApplicationContext实例。根据引用内容,我记得当Bean实现这个接口后,Spring容器会在创建Bean的时候自动调用setApplicationContext方法,把容器本身传进去。这样Bean就能保存这个引用,进而访问容器中的其他Bean了。 接下来,我需要整理回答的结构。首先解释接口的作用,然后说明原理,可能还需要提到应用场景。引用里提到,接口允许获取ApplicationContext,从而能访问所有Bean,这在需要动态获取Bean的时候很有用,比如工具类或者需要与其他Bean交互的情况。 另外,用户可能想知道具体的实现机制。根据引用3,Spring容器会检测所有Bean,如果发现实现了这个接口,就会在创建Bean后调用setApplicationContext方法,传入容器实例。这样Bean内部就可以保存这个引用,比如保存到一个静态变量中,方便其他地方使用。 需要注意,回答要符合用户的要求,结构清晰,分点说明。还要引用提供的参考资料,正确标注引用标识。例如,在解释原理的时候引用[^3],在说明作用的时候引用[^1][^2]。 可能还需要提到使用这个接口的注意事项,比如避免过度依赖Spring上下文,保持代码的松耦合。但用户的问题主要关注原理和作用,这部分可以简要带过。 最后,生成相关问题的时候,要围绕接口的使用场景、替代方案、生命周期等,确保问题相关且有价值。</think>### Spring ApplicationContextAware接口原理及作用 #### 一、接口作用 1. **获取ApplicationContext实例** 通过实现`ApplicationContextAware`接口Bean可以直接获取当前Spring容器的`ApplicationContext`对象。这使得Bean能够动态访问容器中的其他Bean、资源文件或容器事件[^1][^2]。 2. **访问容器管理的所有Bean** 持有`ApplicationContext`后,可以通过`getBean()`方法按名称或类型获取容器中已注册的Bean实现灵活的依赖注入或运行时动态调用。 3. **扩展容器功能** 适用于需要与Spring容器深度交互的场景,例如工具类需要根据配置动态加载Bean,或框架扩展组件需要感知容器状态。 #### 二、实现原理 1. **接口回调机制** Spring容器在初始化Bean时,会检查其是否实现了`ApplicationContextAware`接口。若实现,则调用`setApplicationContext(ApplicationContext context)`方法,将当前容器实例注入到Bean中[^3]。 2. **依赖注入的特殊形式** 与常规的`@Autowired`不同,此接口是Spring提供的**生命周期回调接口**,属于底层扩展点。容器主动将自身引用传递给Bean,无需额外配置。 3. **典型代码实现** ```java public class SpringContextUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext context) { applicationContext = context; // 保存容器引用 } public static <T> T getBean(Class<T> beanType) { return applicationContext.getBean(beanType); } } ``` 通过静态变量存储`ApplicationContext`,其他类可直接通过工具类获取Bean[^3]。 #### 三、注意事项 - **避免滥用**:过度依赖`ApplicationContext`会破坏依赖注入的设计原则,导致代码与Spring框架紧耦合。 - **线程安全**:若在多线程环境中使用,需确保对`ApplicationContext`的操作是线程安全的。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值