Spring源码解析 - SpringApplication 属性-初始化initializers, listeners -Spring提供的钩子函数

发布于:2025-08-09 ⋅ 阅读:(12) ⋅ 点赞:(0)

初始化源码

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	~~~
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	~~~
}


private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    // 获取当前 SpringApplication 实例的类加载器
    // 这个类加载器将用于加载类和资源
    ClassLoader classLoader = getClassLoader();
    
    // 从 META-INF/spring.factories 文件中加载指定类型的工厂类名称
    // 使用 LinkedHashSet 保证加载的类名称的顺序,并且去除重复项
    // SpringFactoriesLoader.loadFactoryNames(type, classLoader) 会读取 spring.factories 文件中指定类型的类名称
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    
    // 根据加载的类名称,反射创建指定类型的实例
    // createSpringFactoriesInstances 方法会根据类名称和构造函数参数类型及参数值,反射创建实例
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    
    // 根据 @Order 注解或实现 Ordered 接口的顺序对实例进行排序
    // AnnotationAwareOrderComparator.sort(instances) 会根据 @Order 注解或 Ordered 接口的值对实例进行排序
    AnnotationAwareOrderComparator.sort(instances);
    
    // 返回创建并排序后的实例集合
    return instances;
}

SpringApplication中 initializers 钩子实现

1. 实现 ApplicationContextInitializer 接口

你需要创建一个类,实现 ApplicationContextInitializer 接口,并在 initialize 方法中实现自定义的初始化逻辑。

public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // 在这里执行自定义逻辑
        System.out.println("Executing custom logic before Spring context refresh");
        // 例如,设置环境变量
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        environment.setProperty("custom.property", "customValue");
    }
}
2. 注册初始化器

你可以在 SpringApplication 的构造方法中显式注册这些初始化器,或者通过 META-INF/spring.factories 文件自动发现它们。

显式注册

SpringApplication 的构造方法中显式注册初始化器:

public class MyApplication {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(MyApplication.class);
        
        // 显式注册初始化器
        application.addInitializers(new MyApplicationContextInitializer());
        
        application.run(args);
    }
}
通过 META-INF/spring.factories 文件自动发现

resources 目录下创建或编辑 META-INF/spring.factories 文件,并添加你的初始化器类:

org.springframework.context.ApplicationContextInitializer=\
com.example.MyApplicationContextInitializer

初始化器的执行顺序

  • ApplicationContextInitializer:在 Spring 容器刷新之前执行。
  • ApplicationRunnerCommandLineRunner:在 Spring 容器刷新之后执行。
    ApplicationListener 是 Spring 提供的一个接口,用于监听 Spring 应用上下文中的事件。通过实现 ApplicationListener 接口,你可以捕获并处理特定的事件,从而在 Spring 应用的生命周期中执行自定义逻辑。

以下是使用 ApplicationListener 钩子的步骤和示例代码:


SpringApplication中listeners 钩子实现

ApplicationListener接口继承自Java的EventListener接口,表示一个事件监听器,它能够接收并处理特定类型的事件。在Spring中,当一个事件被发布时(通常是通过ApplicationContext的publishEvent方法),Spring会查找所有实现了ApplicationListener接口并且声明了要监听的事件类型的Bean,然后调用这些Bean的onApplicationEvent方法来处理事件。

1. 实现 ApplicationListener 接口

你需要创建一个类,实现 ApplicationListener 接口,并重写 onApplicationEvent 方法。onApplicationEvent 方法会在事件发生时被调用。

示例代码
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // 在这里执行自定义逻辑
        System.out.println("Application is ready and fully started!");
        // 你可以在这里执行一些初始化逻辑或检查
    }
}

2. 监听特定事件

Spring 提供了多种事件类型,例如:

  • ContextRefreshedEvent:在 Spring 容器刷新时触发。
  • ApplicationReadyEvent:在 Spring 应用完全启动后触发。
  • ContextStartedEvent:在 Spring 容器启动时触发。
  • ContextStoppedEvent:在 Spring 容器停止时触发。
  • ContextClosedEvent:在 Spring 容器关闭时触发。

你可以选择监听特定的事件类型。例如,如果你想在应用启动后执行一些逻辑,可以监听 ApplicationReadyEvent

3. 自定义事件

你还可以定义自己的事件类型,并在需要的时候发布这些事件。

定义自定义事件
import org.springframework.context.ApplicationEvent;

public class MyCustomEvent extends ApplicationEvent {
    private String message;

    public MyCustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}
发布自定义事件
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
public class MyService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void doSomething() {
        // 执行一些业务逻辑
        System.out.println("Doing something...");

        // 发布自定义事件
        MyCustomEvent customEvent = new MyCustomEvent(this, "Custom event message");
        eventPublisher.publishEvent(customEvent);
    }
}
监听自定义事件
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyCustomEventListener implements ApplicationListener<MyCustomEvent> {
    @Override
    public void onApplicationEvent(MyCustomEvent event) {
        // 在这里处理自定义事件
        System.out.println("Received custom event: " + event.getMessage());
    }
}

4. 使用注解方式监听事件

除了实现 ApplicationListener 接口,你还可以使用 @EventListener 注解来监听事件。


网站公告

今日签到

点亮在社区的每一天
去签到