【问题标题】:Refreshing Grails applicationContext刷新 Grails applicationContext
【发布时间】:2010-11-25 18:47:22
【问题描述】:

在我的配置的 spring/resources.xml 文件中,我定义了一个这样的 bean:

<bean id="myService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
    <property name="serviceUrl" value="http://${remote.host}:8080/MyAgent/remoting/MyService"/>
    <property name="serviceInterface" value="services.MyService"/>
</bean>

在我的 Config.groovy 文件中,我有: remote.host = "someipaddress"

现在我想在运行时更改这个占位符的值。在常规的 spring 应用程序中,我通过 PropertyPlaceHolderConfigurer 执行此操作,然后刷新上下文并且它可以工作。

在 Grails 中,如何刷新上下文?

问候,

菲利普

【问题讨论】:

  • 如果我没有误会,您是在问如何刷新上下文(您可以随时重新启动服务器,或重新部署应用程序 - 因为您不是每次都更改设置天),但主要问题是如何在不重新编译的情况下替换remote.host。 - 对吗?
  • 不...它是随时动态替换remote.host,因为我将连接到托管在不同主机上的多个远程服务。 (是的,我知道也许这不应该是单例,但这并不能解决我的刷新问题......)

标签: java spring grails


【解决方案1】:

好的,我放弃了提神醒脑的方法。 作为一种解决方法,我创建了一个如下所示的 grails 服务:

class myService {
    def myRemoteService
    static transactional = false

    private MyRemoteService getService(String remoteServiceURL) {
        HessianProxyFactory factory = new HessianProxyFactory();
        try {
            return (MyRemoteService) factory.create(MyRemoteService.class, url);
        }
        catch (MalformedURLException e) {
            e.printStackTrace()
        }
        return null
    }

    def someRemoteMethod(String remoteServiceURL) {
        getService(remoteServiceURL).myRemoteMethod()
    }
}

这允许我在任何远程机器上动态调用远程服务。

我仍然对更简洁的解决方案感兴趣,因为这让我为每个远程方法重写了一个包装器方法:-S

【讨论】:

    【解决方案2】:

    为什么不直接更新值:

    def blabla
    ...
    void someServiceMethod() {
       blabla.someProperty = 'new value'
    }
    

    def blabla
    ...
    def someControllerAction = {
       blabla.someProperty = 'new value'
    }
    

    【讨论】:

    • 没错,但在我的情况下,bean 实际上是一个动态代理(org.springframework.aop.framework.JdkDynamicAopProxy),所以我无法直接访问代理的字段界面。
    【解决方案3】:

    grailsApplication暴露了一个refresh()方法,我不确定它是否会重新加载spring上下文,你可以试试。

    【讨论】:

    • 好吧,grailsApplication.mainContext 应该是可刷新的,但我明白了:2010-11-26 12:10:27,841 [http-8080-1] ERROR errors.GrailsExceptionResolver - GenericApplicationContext 不支持多次刷新尝试:只需调用一次'refresh' java.lang.IllegalStateException:GenericApplicationContext 不支持多次刷新尝试:只需在 java.lang.Thread.run(Thread. java:680)
    【解决方案4】:

    我在 grails 邮件列表中进行了快速搜索,看起来 grails 不支持 app-context 重新加载。

    您可以尝试实现 InitializingBean 并直接从应用配置中获取值。

    import org.springframework.beans.factory.InitializingBean
    
    class ExampleService implements InitializingBean { 
    
       def grailsApplication 
       def setting
    
       void afterPropertiesSet() { 
          this.setting = grailsApplication.config.setting 
       }
    }
    

    也许您可以在每次需要使用时监听配置中的更改或获取属性,我不知道,我现在无法创建应用程序来运行一些测试。

    【讨论】:

    • 谢谢,但我的服务未定义为我可以在我的应用程序中控制的 Grails 服务。它是一个部署在远程 tomcat 上的 java 服务,通过 Hessian 暴露。在我的 grails 应用程序中,我只有服务接口,我通过 HessianProxyFactoryBean 配置对远程服务的访问...
    【解决方案5】:

    未测试,但尝试:

    import grails.spring.BeanBuilder
    
    def bb = new BeanBuilder(
            application.parentContext,
            new GroovyClassLoader(application.classLoader))
    def beans = bb.beans {
        myService(org.springframework.remoting.caucho.HessianProxyFactoryBean) {
            ...
        }
    }
    beans.registerBeans(application.mainContext)
    

    这几乎是插件在需要交换新的 bean 实例时所做的事情。您还可以提出一个 JIRA 问题以获得更好的方法。

    【讨论】:

    • 这种方法在运行时刷新上下文方面有什么区别?
    • 两个区别:1. 您可以为给定的 ID 注册全新的 bean 2. 它可以工作,而 .refresh() 显然不能;虽然我没有测试过。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多