使用参数注入bean的最佳模式是什么?

时间:2015-11-16 18:18:10

标签: spring grails factory-pattern

我的应用程序中有很多案例,其中客户端代码想要按需创建bean。在每种情况下,bean都有1或2个构造函数参数,这些参数由客户端方法指定,其余的是自动装配的。

例如:

//client code
MyQuery createQuery() {
    new MyQuery(getSession())
}

//bean class I want to create
//prototype scoped
class MyQuery {
    PersistenceSession session
    OtherBeanA a
    OtherBeanB b
    OtherBeanC c
}

我想要A,B和C自动装配,但我要求“会话”#39;必须由调用代码指定。我想要一个像这样的工厂界面:

interface QueryFactory {
    MyQuery getObject(PersistenceSession session)
}

连接工厂最有效的方法是什么?是否可以避免编写new MyQuery(...)的自定义工厂类? ServiceLocatorFactoryBean可以用于这样的事情吗?

1 个答案:

答案 0 :(得分:0)

您可以在其他bean上使用@Autowired注释,然后使用ApplicationContext注册新bean。这假设otherBeanA是现有的bean。

import org.springframework.beans.factory.annotation.Autowired

class MyQuery {
    @Autowired  
    OtherBeanA otherBeanA

    PersistenceSession persistenceSession

    public MyQuery(PersistenceSession ps){
        this.persistenceSession = ps
    }
}

如果这是创建新bean的最有效方法,我不肯定,但它似乎是运行时的最佳方式。

import grails.util.Holders
import org.springframework.beans.factory.config.ConstructorArgumentValues
import org.springframework.beans.factory.support.GenericBeanDefinition
import org.springframework.beans.factory.support.AbstractBeanDefinition
import org.springframework.context.ApplicationContext

class MyQueryFactory {
    private static final String BEAN_NAME = "myQuery"

    static MyQuery registerBean(PersistenceSession ps) {
        ApplicationContext ctx = Holders.getApplicationContext()

        def gbd = new GenericBeanDefinition(
                beanClass: ClientSpecific.MyQuery,
                scope: AbstractBeanDefinition.SCOPE_PROTOTYPE,
                autowireMode:AbstractBeanDefinition.AUTOWIRE_BY_NAME
            )

        def argumentValues = new ConstructorArgumentValues()
        argumentValues.addGenericArgumentValue(ps)
        gbd.setConstructorArgumentValues(argumentValues)

        ctx.registerBeanDefinition(BEAN_NAME, gbd)

        return ctx.getBean(BEAN_NAME)
    }
}

建议不要使用Holders,而是建议使用依赖注入的ApplicationContext(如果可用),然后将其传递给registerBean方法。

static MyQuery registerBeanWithContext(PersistenceSession ps, ApplicationContext ctx) {
    ...
}   

致电课程:

def grailsApplication    
...
PersistenceSession ps = getRuntimePersistenceSession()

MyQueryFactory.registerBean(ps, grailsApplication.mainContext)

我更改了方法的名称以真实地反映它正在做的事情 - 注册一个spring bean而不是实例化MyQuery。我使用getBean方法传回bean,但是一旦创建了ApplicationContext,你也可以访问同一个bean。

def myQueryBean = MyQueryFactory.registerBean(ps)
// or somewhere other than where the factory is used
def grailsApplication
def myQueryBean = grailsApplication.mainContext.getBean('myQuery')