You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Grails 5.2.5重新编译后会触发哪些初始化事件?

Grails自动编译后的初始化行为与触发事件

首先要明确:Grails开发模式下的自动编译/类重新加载,和应用完整启动是完全不同的流程——它仅针对变更的类进行局部更新,不会重复执行全局启动初始化逻辑,这就是你遇到BootStrap.init、GrailsAutoConfiguration相关方法不触发的核心原因。

自动编译时会触发的行为与事件

  • 旧Bean实例销毁:当变更类对应的Bean被替换时,容器会销毁旧实例,此时带有@PreDestroy注解的方法会被执行,这也是你能观察到该注解生效的原因。
  • 变更类的重新加载:新编译的类会被Grails的自定义类加载器加载,对于标记为可重新加载的Bean(默认包括控制器、服务、领域类等业务组件),容器会创建新的Bean实例。
  • Spring容器局部刷新:仅针对变更Bean所在的上下文进行局部刷新,不会触发全局的上下文初始化事件。

不会触发的初始化逻辑

这些操作仅在应用首次启动/完整重启时执行,自动编译阶段完全跳过:

  • Bootstrap.groovy中的init方法
  • GrailsAutoConfiguration类的doWithApplicationContext、onStartup等启动钩子
  • JSR标准的@PostConstruct注解方法(注:如果Bean被正确重新创建,理论上该方法应执行,但如果你的服务Bean未被标记为可重新加载,或者容器采用了特殊的实例替换逻辑,可能导致该注解不生效)
  • 全局应用生命周期事件(如ApplicationReadyEvent、ContextStartedEvent)

实现自定义类重载后初始化的方案

如果需要在类重新加载后执行自定义初始化逻辑,可以尝试以下方式:

  1. 实现ReloadListener接口:
    实现Grails提供的org.codehaus.groovy.grails.commons.spring.ReloadListener,重写onReload方法,该方法会在类重新加载完成后被调用。示例:

    class MyReloadListener implements ReloadListener {
        void onReload(Map<String, Object> reloadContext) {
            // 自定义初始化逻辑
            println "类已重新加载,执行初始化"
        }
    }
    

    然后将该类注册为Spring Bean即可。

  2. 利用Spring的@EventListener监听局部刷新事件:
    监听ContextRefreshedEvent,但需要判断是否是局部刷新场景,避免在完整启动时重复执行:

    @Service
    class MyService {
        @EventListener
        void onContextRefresh(ContextRefreshedEvent event) {
            // 判断是否为局部刷新(可通过上下文的属性或变更类信息判断)
            if (event.applicationContext.parent != null) {
                // 自定义初始化逻辑
            }
        }
    }
    
  3. 手动在类加载时执行初始化:
    对于服务类,可以在类中添加静态初始化块,类重新加载时静态块会再次执行:

    @Service
    class MyService {
        static {
            // 类加载时执行的初始化逻辑
            println "MyService类已加载"
        }
    }
    

内容的提问来源于stack exchange,提问作者Viktor Kalashnykov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:45:29