装饰由Grails提供的Spring bean

时间:2014-05-08 15:19:03

标签: spring grails

我知道我可以通过定义自己的同名bean来替换Grails提供的Spring bean。例如,如果我想替换Grails提供的messageSource bean

class MyMessageSource implements MessageSource {
    // methods omitted
}

然后在resources.groovy

中添加以下内容
messageSource(MyMessageSource)

但是,假设我希望MyMessageSource装饰Grails提供的这个bean的实现

class MyMessageSource implements MessageSource {

    // this field should be set to the MessageSource impl provided by Grails
    MessageSource messageSource
}

我无法弄清楚如何在resources.groovy中进行连线。显然我不能这样做:

messageSource(MyMessageSource) {
    messageSource = ref('messageSource')
}

因为我看起来像是在定义依赖于自身的bean。我当然可以给我的豆子命名,例如

myMessageSource(MyMessageSource) {
    messageSource = ref('messageSource')
}

但是,任何超出我控制范围的类(例如插件类)声明对messageSource的依赖都将被设置为Grails而不是我的装饰器提供的bean。

2 个答案:

答案 0 :(得分:7)

在一个应用程序(不是一个插件)中,沿着这些行的东西应该有用......

新讯息来源:

// src/groovy/com/demo/MyMessageSource.groovy
package com.demo

import org.springframework.context.MessageSource
import org.springframework.context.MessageSourceResolvable
import org.springframework.context.NoSuchMessageException

class MyMessageSource implements MessageSource {
    MessageSource theRealMessageSource

    String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
        theRealMessageSource.getMessage code, args, defaultMessage, locale
    }

    String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
        theRealMessageSource.getMessage code, args, locale
    }

    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
        theRealMessageSource.getMessage resolvable, locale
    }
}

后处理器:

// src/groovy/com/demo/MyPostProcessor.groovy
package com.demo

import org.springframework.beans.factory.config.BeanFactoryPostProcessor
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.BeansException

class MyPostProcessor implements BeanFactoryPostProcessor {

    @Override
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // error handling ommitted for brevity here...

        def realMessageSource = beanFactory.getBean('messageSource')
        def newMessageSource = new MyMessageSource()
        newMessageSource.theRealMessageSource = realMessageSource

        beanFactory.removeBeanDefinition 'messageSource'
        beanFactory.registerSingleton 'messageSource', newMessageSource
    }
}

注册后处理器:

// grails-app/conf/spring/resources.groovy
beans = {
    myMessageSourcePostProcessor com.demo.MyPostProcessor
}

答案 1 :(得分:1)

初始化上下文后,您可以检索messageSource bean,创建委托给messageSource bean的bean实例,然后使用名称" messageSource"中的上下文注册您的bean。所以当DI发生时,你的bean就是将被使用的bean。在插件中,您应该能够在doWithApplicationContext(而不是doWithSpring)中执行此操作。