我有一个类似的问题,但对我来说,我想使用一个工厂来使用 JMockit(我需要使用的测试框架)创建我的自动连接依赖项的模拟实现。
在互联网上找不到令人满意的解决方案后,我整理了一个对我来说非常有效的简单解决方案。
我的解决方案也使用了 Spring FactoryBean
,但它只使用一个工厂 bean 来创建我所有的 bean(最初的询问者似乎希望这样做)。
我的解决方案是实现一个工厂工厂元工厂,为FactoryBean
真实的单一工厂提供包装器。
这是我的 JMockit 模拟 bean 工厂的 Java:
public class MockBeanFactory<C> implements FactoryBean<C> {
private Class<C> mockBeanType;
protected MockBeanFactory(){}
protected <C> C create(Class<C> mockClass) {
return Mockit.newEmptyProxy(mockClass);
}
@Override
public C getObject() throws Exception {
return create(mockBeanType);
}
@Override
public Class<C> getObjectType() {
return mockBeanType;
}
@Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
public <C> MockBeanFactory<C> createFactory(Class<C> mockBeanType) {
MockBeanFactory<C> factory = new MockBeanFactory<C>();
factory.mockBeanType = mockBeanType;
return factory;
}
}
}
然后在 Spring 上下文 XML 文件中,您可以简单地创建创建特定 bean 类型工厂的元工厂:
<bean id="metaFactory" class="com.stackoverflow.MockBeanFactory$MetaFactory"/>
<bean factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="mockBeanType" value="com.stackoverflow.YourService"/>
</bean>
为了使这适用于原始询问者的情况,可以对其进行调整以将其FactoryBeans
变为包装器/适配器serviceFactoryBean
:
public class FancyFactoryAdapter<C> implements FactoryBean<C> {
private Class<C> clientClass;
private FancyFactory serviceFactoryBean;
protected FancyFactoryAdapter(){}
@Override
public C getObject() throws Exception {
return serviceFactoryBean.buildService(clientClass);
}
@Override
public Class<C> getObjectType() {
return clientClass;
}
@Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
@Autowired FancyFactory serviceFactoryBean;
public <C> FancyFactoryAdapter<C> createFactory(Class<C> clientClass) {
FancyFactoryAdapter<C> factory = new FancyFactoryAdapter<C>();
factory.clientClass = clientClass;
factory.serviceFactoryBean = serviceFactoryBean;
return factory;
}
}
}
然后在 XML 中(注意userServiceFactory
id 和userService
bean id 仅用于使用@Qualifier
注解):
<bean id="metaFactory" class="com.stackoverflow.FancyFactoryAdapter$MetaFactory"/>
<bean id="userServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.UserServiceInterface"/>
</bean>
<bean id="userService" factory-bean="userServiceFactory"/>
<bean id="scoreServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.ScoreServiceInterface"/>
</bean>
<bean id="scoreService" factory-bean="scoreServiceFactory"/>
就是这样,只需一个小的 Java 类和一点样板配置以及您的自定义 bean 工厂就可以创建所有 bean 并让 Spring 成功解决它们。