2015-11-16 33 views
2

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

例:

//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作为自动连接,但我有一个“会话”必须由调用代码中指定的要求。我想要一个像这样的工厂接口:

interface QueryFactory { 
    MyQuery getObject(PersistenceSession session) 
} 

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

+0

您是否找到了实现bean按需的方法?我很好奇,如果我的解决方案帮助,或者如果你使用另一种方法。 – tylerwal

+0

感谢您的回复!不幸的是,我正在解决一个不同项目的展示瓶塞问题,所以我还没有尝试。我会尽快检查出来,并告诉你是否有帮助。 =) – RMorrisey

回答

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的,它建议使用从dependecy的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') 
相关问题