我的应用程序中有很多案例,其中客户端代码想要按需创建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可以用于这样的事情吗?
答案 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')