5

简短的问题是:每当热编译和换入新代码时,我是否可以强制 Grails 2.2 开发服务器重新加载(重新初始化所有单例服务等)?

让我用一个例子来说明这个问题。让我们这么说

  1. 我有一个名为MyService. 在其@PostConstruct函数中,它初始化一个新的类型对象Helper(并保留引用)。

  2. run-app在开发模式下,测试一下,然后......

  3. 我编辑源代码Helper.groovy

接下来发生的是:

  • Grails 自动重新编译Helper.groovy
  • Grails 将新代码交换到正在运行的开发服务器中
  • Helper但是没有调用新代码,因为已经实例化的MyService对象已经拥有旧类型实例的句柄。

我目前的解决方法是在我的脑海中保留一个依赖关系图,或者每次我更改它的依赖关系之一时都进行touchMyService简单的修改。但我宁愿在换入新代码时强制开发服务器完全重新加载。

那么......是否可以在任何代码更改时强制开发服务器重新加载

还有一个额外的问题:当我更改域对象时,我可以强制开发服务器“遵循”这些更改的唯一方法是stop-app手动clean执行run-app。我可以在需要时自动执行此操作吗?

谢谢!

4

1 回答 1

5

重要更新

我能够得到你正在寻找的东西。逐步放下它:

要求-修改类
时,应刷新类以引用修改后的辅助类。Helperservice

设置

//src/groovy
class SampleHelper {
    String name = 'Heisenberg'

    def sayMyName(){
        "$name"
    }
}

//grails-app/service
import javax.annotation.PostConstruct
class SampleService {
    String cachedName

    @PostConstruct
    def initIt(){
        cachedName = new SampleHelper().sayMyName()
    }

    def serviceMethod() {
        cachedName
    }
}

//controller
class SampleController {
    def sampleService

    def index() {
        render sampleService.serviceMethod()
    }
}

问题陈述
name帮助类更新为Gus时,该类会刷新,但服务类仍引用 的旧实例SampleHelper。结果,名称仍然显示Heisenberg

解决方案

  • 观看助手类。
  • 刷新onChange助手类的服务类。

这可以通过在应用程序中使用Pluginator 插件来实现,该插件可以灵活地监视文件并执行某些onChange事件。

  • 安装插件。
  • 在下面添加以下ApplicationPlugin.groovy内容grails-app/conf

作为

class ApplicationPlugin {
    //Watch the helper class
    def watchedResources = "file:./src/groovy/**/*.groovy"

    //Re-Register the bean (service class) onChange of Helper Class
    //This can be generalized more.
    def onChange = { event ->
        if (event.source) {
            def beans = beans {
                sampleService(SampleService) { bean ->
                    bean.autowire =  true
                }
            }
            if (event.ctx) {
                event.ctx.registerBeanDefinition(
                        "sampleService",
                        beans.getBeanDefinition("sampleService"))
            }
        }
    }
}
  • 遵循上述步骤后,问题陈述应得到修复。

笔记

  • 如果所有类和人工制品都遵循此过程,则可能会占用大量资源。

旧的和有效的答案

我无法在 Grails 2.2.0 中重现您的问题。以下是我的设置(如果我在任何地方错了,请纠正我):

//src/groovy
class MyHelper{
    def sayMyName(){
        "Heisenberg"
    }
}

//service
import javax.annotation.PostConstruct
class MyService {
    def myHelper

    @PostConstruct
    def initIt(){
        myHelper = new MyHelper()
    }

    def serviceMethod() {
        myHelper.sayMyName()
    }
}

//controller (to test)
class MyController {
    def myService

    def index() {
        render myService.serviceMethod()
    }
}

脚步:

  • 运行初始设置。( run-app)
  • 点击控制器查看“海森堡”
  • 修改MyHelper.sayMyName()以返回“Walter White”而不是“Heisenberg”
  • 再次点击控制器并看到“Walter White”

观察:

  • 我宁愿制作MyHelper一个bean并在服务类中使用(注入)它以供使用。

进入resources.groovy如下:

beans = {
    myHelper(com.example.MyHelper)
}

服务类变为:

class MyService {
    def myHelper

    def serviceMethod() {
        myHelper.sayMyName()
    }
}
  • 现在,在服务类中引用字段MyHelper会产生问题,因为 bean 已经在容器中实例化了

关于奖金问题:

我无法在 Grails 2.2.0 中重现该问题

//domain
class MyDomain {
    String name
}

//controller action
def add(){
    def myDomain = new MyDomain(name: 'Testing').save(flush: true)
    render myDomain.properties
}
  • 更改域,添加String email
  • 保存域类。
  • 修改要添加email的操作MyDomain(显然将创建一个新行)。
  • 保存控制器。
  • 再次击中动作。
  • 查看结果。
于 2013-08-23T15:27:28.213 回答