【问题标题】:Override Grails service bean definition with plugin使用插件覆盖 Grails 服务 bean 定义
【发布时间】:2013-02-10 14:33:01
【问题描述】:

我想通过仅安装插件来覆盖服务实现 - 安装插件时,我希望使用服务的插件版本,当卸载插件时,我希望使用服务的默认版本.

为避免浪费时间,我将使用代码解释我的问题。我有一个由我的主应用程序和我的“自定义插件”共享的“通用插件”,其中包含以下内容:

public interface SimpleService {
    void doProcessing();
}

然后我有一个包含以下内容的“主应用程序”

服务接口的默认实现:

public DefaultSimpleService implements SimpleService {
    void doProcessing() {
        // ...
    }

resource.groovy:

simpleService(DefaultSimpleService) { bean ->
    bean.autowire = 'byName'
}

使用服务的控制器:

class SimpleController {
    def simpleService

    def index() {
        simpleService.doProcessing()
    }
}

到目前为止一切顺利。我现在要做的就是通过安装一个插件来用一个新的接口替换SimpleService 接口的实现。我不想更改我的应用程序中的任何配置。

我有一个带有新服务实现的插件:

public CustomSimpleService implements SimpleService {
    void doProcessing() {
        // ...
    }
}

我的第一次尝试是在插件“doWithSpring”部分注册自定义服务 bean,但它总是被主应用程序覆盖。很公平,因为似乎插件总是在注册主应用程序 bean 之前加载(?)

我的第二次尝试是在我的 CustomServiceGrailsPlugin.groovy 中的“doWithApplicationContext”中注册自定义 bean:

def doWithApplicationContext = { applicationContext ->
    DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory()
    beanFactory.registerBeanDefinition("simpleService", BeanDefinitionBuilder.rootBeanDefinition(CustomSimpleService.class.getName()).getBeanDefinition())
}

这实际上是部分工作 - 当插件被加载时,使用 SimpleService 的插件实现,如果插件被卸载,则使用 SimpleService 的主要应用程序实现。但是有一个附带问题:bean 的自动装配在“手动”注册的插件实现中不起作用......

然后我开始查看BeanPostProcessors,但从我读到的内容看来它不能解决我的问题。

那么我该如何解决我的问题呢?

问候 托比

【问题讨论】:

  • 这应该如何工作?插件不能对主机应用程序定义的类进行静态引用,所以public CustomSimpleService implements SimpleService 不应该编译......而且你是正确的,主应用程序定义的 bean 覆盖了插件定义的那些,这就是它应该如何工作。
  • 好吧.. 这是一种简化,在现实世界中,接口定义驻留在另一个插件中,该插件由主应用程序和“自定义插件”导入。但是知道我如何覆盖实现吗?除了 registerBeanDefinition(不包括自动装配)

标签: grails


【解决方案1】:

我认为你最好的办法是检查插件是否已安装,如果是,请不要在应用程序中声明服务。

您可以检查安装的插件:org.codehaus.groovy.grails.plugins.PluginManagerHolder.pluginManager.allPlugins

你可以在 resources.groovy 中使用它

boolean containsPlugin(String pluginName) {
    def names = org.codehaus.groovy.grails.plugins.PluginManagerHolder.pluginManager.allPlugins.collect { it -> return it.name }  
    return(pluginName in names) 
}


beans = {
  if(!containsPlugin("thePlugin")) {
    println "Installation not contains plugin, defining bean!"
    myService(...)
  }
}

【讨论】:

  • OP 希望特定 bean 的 custom plugin 定义优先于 host app 中相同 bean 名称的定义,而不是通用插件。
  • 我想这已经很好了(所以我将其标记为答案),我不喜欢在代码中包含插件名称,但如果我这样做,我会将其移至配置至少。非常感谢您抽出宝贵时间!
猜你喜欢
  • 2011-10-31
  • 1970-01-01
  • 2014-11-03
  • 2023-03-16
  • 2016-06-08
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多