2015-11-16 59 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') 
相關問題