Skip to content

实际上,[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50)方法确实会被Spring容器自动调用,让我来解释一下这个过程是如何发生的。

当一个类实现了ApplicationContextAware接口时,Spring框架会自动识别这一点,并在Bean初始化过程中调用[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50)方法。这个过程是由Spring容器内部的机制完成的,不需要显式的调用。

具体流程如下:

  1. Bean实例化:Spring容器创建[LockInfoHandleFactory](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L23-L52) Bean实例
  2. Aware接口检测:Spring检测到该Bean实现了ApplicationContextAware接口
  3. 自动调用:Spring容器自动调用[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50)方法,传入当前的ApplicationContext实例
  4. 依赖注入完成:此时[applicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L30-L31)字段已经被赋值,可以在其他方法中使用

这个工作机制依赖于Spring的以下特性:

  1. Aware接口处理机制:Spring内部有一套机制来处理各种Aware接口(如ApplicationContextAware、BeanNameAware等)
  2. BeanPostProcessor:Spring使用BeanPostProcessor来处理Aware接口,在适当的时机调用相应的方法

查看一下这个类是否被注册为Spring Bean:

现在我可以清楚地回答你的问题了。你提到的[selectedCode](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L42-L51)中的[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50)方法确实是会被调用的,只是不是通过显式的代码调用,而是由Spring框架自动调用的。

Spring容器如何自动调用setApplicationContext

正如我在前面解释的,当Spring容器创建并初始化一个实现了ApplicationContextAware接口的Bean时,它会自动检测到这个接口,并在适当的时候调用[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50)方法。

LockInfoHandleFactory是如何注册为Spring Bean的

通过查看代码,我们可以看到在[RedissonCommonAutoConfiguration](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/config/RedissonCommonAutoConfiguration.java#L35-L136)类中有以下配置:

java
@Bean
public LockInfoHandleFactory lockInfoHandleFactory(){
    return new LockInfoHandleFactory();
}

这表明[LockInfoHandleFactory](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L23-L52)被注册为一个Spring Bean。

完整的流程

  1. Bean注册:通过[RedissonCommonAutoConfiguration.lockInfoHandleFactory()](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/config/RedissonCommonAutoConfiguration.java#L134-L135)方法,[LockInfoHandleFactory](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L23-L52)被注册为Spring Bean
  2. Bean实例化:Spring容器创建[LockInfoHandleFactory](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L23-L52)实例
  3. Aware接口处理:Spring检测到该Bean实现了ApplicationContextAware接口
  4. 自动调用:Spring框架自动调用[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50)方法,将ApplicationContext注入到[applicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L30-L31)字段中
  5. 正常使用:之后就可以在[getLockInfoHandle](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L37-L39)方法中使用[applicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L30-L31)来获取其他Bean了

这种方式是Spring框架的标准做法,很多Spring内置的类也是这样工作的,比如各种Aware接口的实现类。你不需要手动调用[setApplicationContext](file://D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L47-L50),Spring会帮你完成这个过程。

让我来解释一下applicationContext.getBean的调用方式。这是Spring框架中一种重要的获取Bean实例的方法。

applicationContext.getBean的调用方式详解

在[LockInfoHandleFactory](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L23-L52)类中,通过以下方式调用[getBean](file://D:\Java_projects\damai\damai-common\src\main\java\com\damai\core\SpringUtil.java#L29-L31)方法:

java
return applicationContext.getBean(lockInfoType, LockInfoHandle.class);

这是[getBean](file://D:\Java_projects\damai\damai-common\src\main\java\com\damai\core\SpringUtil.java#L29-L31)方法的一种重载形式,让我们看看Spring中[getBean](file://D:\Java_projects\damai\damai-common\src\main\java\com\damai\core\SpringUtil.java#L29-L31)的主要调用方式:

1. 按名称获取Bean

java
// 通过Bean名称获取
Object bean = applicationContext.getBean("beanName");

// 通过Bean名称和类型获取(类型安全)
MyService myService = applicationContext.getBean("myService", MyService.class);

2. 按类型获取Bean

java
// 通过类型获取Bean(要求容器中只有一个该类型的Bean)
MyService myService = applicationContext.getBean(MyService.class);

// 在LockInfoHandleFactory中的用法就是这种形式
LockInfoHandle lockInfoHandle = applicationContext.getBean(lockInfoType, LockInfoHandle.class);

3. 按名称和类型获取Bean

java
// 通过Bean名称和类型获取(最安全的方式)
MyService myService = applicationContext.getBean("myService", MyService.class);

LockInfoHandleFactory中的具体应用

在[LockInfoHandleFactory](file:///D:/Java_projects/damai/damai-redisson-framework/damai-redisson-service-framework/damai-redisson-common-framework/src/main/java/com/damai/lockinfo/factory/LockInfoHandleFactory.java#L23-L52)中,使用的是第3种方式:

java
public LockInfoHandle getLockInfoHandle(String lockInfoType){
    return applicationContext.getBean(lockInfoType, LockInfoHandle.class);
}

这里的参数含义:

  • lockInfoType: Bean的名称(同时也是锁信息类型的标识符)
  • LockInfoHandle.class: 期望获取的Bean类型

这种方式的优势:

  1. 类型安全:确保获取的Bean是指定类型的实例
  2. 灵活性:通过参数动态决定获取哪个Bean
  3. 解耦合:工厂类不需要知道所有可能的实现类

实际使用场景

这种设计模式在以下场景中非常有用:

1. 策略模式实现

java
// 根据不同类型获取不同的策略实现
LockInfoHandle handle = lockInfoHandleFactory.getLockInfoHandle("repeatExecuteLimit");
// 或者
LockInfoHandle handle = lockInfoHandleFactory.getLockInfoHandle("serviceLock");

2. 工厂模式实现

java
// 工厂类不需要硬编码所有可能的实现类
public class LockInfoHandleFactory {
    public LockInfoHandle getLockInfoHandle(String type) {
        // 动态获取对应类型的Bean
        return applicationContext.getBean(type, LockInfoHandle.class);
    }
}

相关的Bean定义示例

为了让这种方法工作,需要在Spring配置中定义相应名称的Bean,例如:

java
@Bean("repeatExecuteLimit")
public LockInfoHandle repeatExecuteLimitLockInfoHandle() {
    return new RepeatExecuteLimitLockInfoHandle();
}

@Bean("serviceLock")
public LockInfoHandle serviceLockInfoHandle() {
    return new ServiceLockInfoHandle();
}

这样,当调用lockInfoHandleFactory.getLockInfoHandle("repeatExecuteLimit")时,就会获取到名为"repeatExecuteLimit"且类型为[LockInfoHandle](file://D:\Java_projects\damai\damai-redisson-framework\damai-redisson-service-framework\damai-redisson-common-framework\src\main\java\com\damai\lockinfo\LockInfoHandle.java#L20-L37)的Bean。

这种设计充分利用了Spring框架的依赖注入和Bean管理能力,实现了灵活且松耦合的组件获取机制。