如何在抽象类方法中访问注入的Grails bean?

时间:2014-09-10 20:49:16

标签: spring grails

我有一个抽象类,它实现了大量注册为bean的具体类继承的大部分功能。 bean通过自动装配定义。例如:

abstract class MyAbstract {

    MyService myService
    MyBean myBean

    def doSomething() {
        def value = myService.something(myBean)
    }
}


class MyConcrete extends MyAbstract {
    def concreteField

    def doSomethingElse() {
         def value = myService.somethingElse(myBean)
    }
}

CONF /弹簧/ resources.groovy:

myConcrete(MyConcrete) { bean ->
    bean.autowire = true
    myBean = ref(MySpecificBeanImpl)
}

我的问题:

当我在MyConcrete实例中运行方法doSomethingElse时,一切都按预期工作,并且通过DI用适当的值填充myService和myBean值。当我在MyConcrete实例中执行doSomething方法时,myService和myBean值都为null。似乎DI值在子类继承的抽象方法中不可见。那太糟糕了。

我可以使用方法中的上下文持有者手动访问值,或者我可以使用接受这些值作为参数的修改方法签名将子类中的值传递给抽象父类,但这些都不是好的解决方案。它完全打破了抽象类实现的有用性,并且需要大量复制的代码,而这些代码是我不想要维护的。

更糟糕的是,在我的特定情况下,myBean的值对于每个具体类实际上是不同的,在resources.groovy文件中明确连接,因此泛型持有者方法不起作用。

我查看过与此相关的一些帖子,包括Grails services in abstract class,但没有太多结果来弄清楚发生了什么。抽象bean定义似乎是关于抽象bean定义属性,并不与抽象类和子类继承有关。

(1)这是Grails / Spring DI支持的限制吗? (2)抽象类还有什么我需要做的吗?

2 个答案:

答案 0 :(得分:5)

你遗漏了一些细节,我不得不做出一些假设,但我已经创建了一个类似于你所描述的应用程序。 https://github.com/jeffbrown/abstractbeanmethods项目包含以下内容,似乎有效:

的src /常规/演示/ MyAbstract.groovy     包演示

abstract class MyAbstract {

    MyService myService
    MyBean myBean

    def doSomething() {
        myService.something(myBean)
    }
}

的src /常规/演示/ MyConcrete.groovy

package demo

class MyConcrete extends MyAbstract {
    def doSomethingElse() {
         def value = myService.somethingElse(myBean)
    }
}

的grails-app / CONF /弹簧/ resources.groovy

// Place your Spring DSL code here
beans = {
    myBeanImpl demo.MySpecificBeanImpl

    myConcrete(demo.MyConcrete) { bean ->
        bean.autowire = true
        myBean = ref('myBeanImpl')
    }
}

的src /常规/演示/ MySpecificBeanImpl.groovy     包演示

class MySpecificBeanImpl implements MyBean {
}

的src /常规/演示/ MyBean.groovy

package demo

interface MyBean {}

的grails-app /服务/演示/ MyService.groovy     包演示

class MyService {

    def something(MyBean bean) {
        "Bean class name is ${bean.class.name} in MyService.something() method"
    }
    def somethingElse(MyBean bean) {
        "Bean class name is ${bean.class.name} in MyService.somethingElse() method"
    }
}

的grails-app /控制器/演示/ DemoController.groovy     包演示

class DemoController {
    def myConcrete
    def index() {
        def sb = new StringBuffer()
        sb << myConcrete.doSomething()
        sb << " and "
        sb << myConcrete.doSomethingElse()
        render sb
    }
}

您可能会发现某些事物与您正在做的事情之间存在一些显着差异。如果您可以在该示例应用程序中隔离出有问题的场景,或者提供代码的可运行版本,那么我将很乐意为您解决问题。

答案 1 :(得分:0)

我使用@Autowired注释解决了这个问题

import grails.gorm.services.Service
import org.springframework.beans.factory.annotation.Autowired

@Service(User)
abstract class UserService {

    @Autowired
    OrganizationService organizationService

    //...
}

在Grails 3.3.5上测试