当任何代码重新编译时,我可以强制grails dev服务器重新加载吗?

Bos*_*osh 5 grails groovy tomcat compilation

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

让我用一个例子来说明问题.我们这样说吧

  1. 我有一个单例范围的服务MyService.在它的@PostConstruct函数中,它初始化一个新的类型对象Helper(并保持引用).

  2. run-app在开发模式,测试出来,然后......

  3. 我编辑源代码 Helper.groovy

接下来会发生什么:

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

我目前的解决方法是将依赖图保留在我的脑海中,并且每次更改其中一个依赖项时都会进行touch简单的修改MyService.但是,每当交换新代码时,我宁愿强制dev服务器重新加载.

那么...... 是否有可能在任何代码更改时强制dev服务器重新加载

奖金问题:当我改变域对象,我可以强制开发服务器"追随"的唯一途径这些变化是stop-app,cleanrun-app手动.我是否可以根据需要自动执行此操作?

谢谢!

dma*_*tro 5

关键更新

我能够得到你想要的东西.按顺序放下:

需要量 -
Helper类被修改,service类应该是刷新指修改后的辅助类.

建立

//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()
    }
}
Run Code Online (Sandbox Code Playgroud)

问题声明
name更新helper类时Gus,类会刷新,但服务类仍然引用旧的实例SampleHelper.结果,名称仍然显示Heisenberg.

  • 观看助手课程.
  • 刷新onChange帮助程序类的服务类.

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

  • 安装插件.
  • 下面添加了ApplicationPlugin.groovygrails-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"))
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 在执行上述步骤后,应修复问题陈述.

注意

  • 如果遵循所有类和人工制品,则此过程可能是资源密集型的.

旧有效答案

我无法在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 Code Online (Sandbox Code Playgroud)

脚步:

  • 运行初始设置.(run-app)
  • 击中控制器看"Heisenberg"
  • 修改MyHelper.sayMyName()为返回"Walter White"而不是"Heisenberg"
  • 再次击中控制器并看到"Walter White"

观察:

  • 我宁愿创建MyHelper一个bean并在服务类中使用(注入)它以供使用.

进入resources.groovy如下:

beans = {
    myHelper(com.example.MyHelper)
}
Run Code Online (Sandbox Code Playgroud)

服务类变为:

class MyService {
    def myHelper

    def serviceMethod() {
        myHelper.sayMyName()
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 现在,引用MyHelper服务类中的field in 会产生问题,因为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
}
Run Code Online (Sandbox Code Playgroud)
  • 更改域名,添加 String email
  • 保存域类.
  • 修改要添加email的操作MyDomain(显然将创建一个新行).
  • 保存控制器.
  • 再次点击动作.
  • 看到结果.