【问题标题】:Autowiring custom-made Spring component in Grails在 Grails 中自动装配定制的 Spring 组件
【发布时间】:2014-10-15 03:46:52
【问题描述】:

我有一个定制的 Spring,它捆绑在一个 jar 中,然后将其设置为我的 Grails 应用程序的依赖项。我使用 resoueces.groovy 中的 importBeans 语句为 bean 加载应用程序上下文,例如

beans = {
  importBeans('classpath:app-context-my-component.xml')
}

app-context-my-component.xml 有一些 bean 定义和以下几行

<context:annotation-config />
<context:property-placeholder location="classpath:my-component.properties" />

我尝试与 Grails 一起使用的组件带有 @Component("myComponent") 注释。

Grails 正在加载外部应用程序上下文。我知道这一点是因为我首先在类路径中没有 .properties 文件,并且在我的 @Value 声明中没有用于丢失属性的回退机制。

在Grails控制器中,组件用作

class MyController {

  def myComponent

  def someaction() {
    myComponent.doSomething()
  }
}

结果是 NullPointerException,即组件的自动装配根本不起作用。我尝试在控制器中使用@Autowired,但这给出了一个奇怪的问题,我认为这不是我想走的路。

使用的 Grails 版本是 2.3.6 Spring 组件也设置为使用 Spring 版本 3.2.7 以避免不兼容。

更新

现在又有时间解决这个问题了,我设置了 Spring 日志记录,以便弄清楚发生了什么。好吧,Spring 上下文加载会产生大量日志,但这是我设法从全部中提取的日志

INFO xml.XmlBeanDefinitionReader Loading XML bean definitions from class path resource [app-context-my-component.xml]
INFO support.PropertySourcesPlaceholderConfigurer Loading properties file from class path resource [my-component.properties]
DEBUG framework.CglibAopProxy Unable to apply any optimisations to advised method: public myapp.external.MyComponent myapp.MyService.getMyComponentClient()
DEBUG framework.CglibAopProxy Unable to apply any optimisations to advised method: public myapp.external.MyComponent myapp.MyService.getMyComponentClient()
DEBUG framework.CglibAopProxy Unable to apply any optimisations to advised method: public myapp.external.MyComponent myapp.MyService.getMyComponentClient()
DEBUG framework.CglibAopProxy Unable to apply any optimisations to advised method: public void myapp.MyService.setMyComponentClient(myapp.external.MyComponent)
DEBUG framework.CglibAopProxy Unable to apply any optimisations to advised method: public void myapp.MyService.setMyComponentClient(myapp.external.MyComponent)
DEBUG framework.CglibAopProxy Unable to apply any optimisations to advised method: public void myapp.MyService.setMyComponentClient(myapp.external.MyComponent)

我更改了日志的命名空间,但是myapp.external命名空间是指外部jar包,myapp命名空间是指Grails应用程序命名空间。我已经更改了用法,以便从服务中使用外部组件,而不是直接从控制器中使用,但该细节的行为没有改变。

据我了解,Spring 上下文加载进展顺利。

更新 2

根据 @th3morg 的回答,我想到了仅尝试使用基于 XML 的配置,跳过 bean 中的所有 @Component 和此类注释。它奏效了!现在 Grails 设法导入 bean,不再导致 NPE 使用。

虽然这解决了我的问题,至少部分解决了。我仍然对可以使用 Spring 注释的解决方案感兴趣。

【问题讨论】:

  • 在 Grails 的这一领域还没有真正深入研究,无法给出确定的答案。但是,尝试通过将grails.spring.bean.packages = [ "com.sample.app..." ] 添加到Config.groovy(定义myComponent 的包或父包,Grails 将扫描子包)来告诉Grails 扫描哪个包(s)
  • @Andrew 感谢您的建议,但没有任何效果。
  • 嗯,抱歉导致不好。如果可能的话(考虑到你提到的关于捆绑 jar 的内容,这是一个很长的机会......)你也可以尝试将 Spring XML 移动到 grails-app/conf/spring/ 下名为 resources.xml 的文件中
  • @JAndy 您能否详细说明您希望如何使用注释?您是说 Grails 能够进行组件扫描以连接您的 XML 项目中定义的 bean?在这里查看标题为“使用 Spring 命名空间”的部分 grails.org/doc/latest/guide/…
  • 好吧,我错过了 Spring 配置中的整个组件扫描。将它添加到 resources.groovy 会有所帮助,但是将它放在 Spring 模块上会更简单,因为在 Grails 中只需使用 importBeans()。

标签: spring grails spring-annotations


【解决方案1】:

您应该确保在您的 jar 中设置了组件扫描。在http://grails.org/doc/latest/guide/spring.html#theBeanBuilderDSLExplained 处查看标题为“使用 Spring 命名空间”的部分。如果您无法修改 jar,您还可以使用 resources.xml 并将组件扫描添加到该文件。

或者,您也可以将豆子一根一根地连接起来,虽然这既麻烦又乏味:

beans = {
  myComponent(com.my.MyComponent){
    someOtherService = ref('someOtherService') //if there are other beans to wire by name
    propertyOne = "x"
    propertyTwo = 2
  }
}

【讨论】:

  • 感谢使用调试器的想法。我会看看能不能找到合适的工具。
  • 免费试用 IntelliJ IDEA Ultimate,有效期为 30 天。伟大的 Grails 支持。或者,STS 相当不错且免费。
猜你喜欢
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
相关资源
最近更新 更多