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

Ste*_*ole 2 grails spring

我有一个抽象类,它实现了大量注册为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)
    }
}
Run Code Online (Sandbox Code Playgroud)

CONF /弹簧/ resources.groovy:

myConcrete(MyConcrete) { bean ->
    bean.autowire = true
    myBean = ref(MySpecificBeanImpl)
}
Run Code Online (Sandbox Code Playgroud)

我的问题:

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

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

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

我查看了一些与此相关的帖子,包括抽象类中的Grails服务,但没有太多结果来弄清楚发生了什么.抽象bean定义似乎是关于抽象bean定义属性,与抽象类和子类继承没有任何关系.

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

Jef*_*own 5

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

src/groovy/demo/MyAbstract.groovy包演示

abstract class MyAbstract {

    MyService myService
    MyBean myBean

    def doSomething() {
        myService.something(myBean)
    }
}
Run Code Online (Sandbox Code Playgroud)

SRC /常规/演示/ MyConcrete.groovy

package demo

class MyConcrete extends MyAbstract {
    def doSomethingElse() {
         def value = myService.somethingElse(myBean)
    }
}
Run Code Online (Sandbox Code Playgroud)

的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')
    }
}
Run Code Online (Sandbox Code Playgroud)

src/groovy/demo/MySpecificBeanImpl.groovy包演示

class MySpecificBeanImpl implements MyBean {
}
Run Code Online (Sandbox Code Playgroud)

SRC /常规/演示/ MyBean.groovy

package demo

interface MyBean {}
Run Code Online (Sandbox Code Playgroud)

grails-app/service/demo/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"
    }
}
Run Code Online (Sandbox Code Playgroud)

grails-app/controllers/demo/DemoController.groovy包演示

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

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