今天看一个新项目的代码, 对里面ServiceLocatorFactoryBean的使用不太明白, 便研究了一番。
首先ServiceLocatorFactoryBean的使用场景是这样的, 如果你有一个对象是从spring的beanfactory拿出来,spring的bean一般分为singleton和prototype, singleton是整个spring容器中只有一个实例,prototype是每次注入的时候new一个新实例。但注入一般是注入到对象的属性中,那对于一个对象一般只会注入一次。
假如我每次call一个方法的时候希望都使用的是新的实例, 这时就要靠ServiceLocatorFactoryBean出场了。
官方文档是这样写的
“They will typically be used for prototype beans, i.e. for factory methods that are supposed to return a new instance for each call. ”
具体用法是这样的
首先定义一个接口用来创建之后要使用的目标对象IPhase
interface IPhaseFactory {
IPhase getPhase(String name);
}
然后设置工厂对象,传入这个接口
<beans:bean class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean" id="phaseFactory">
<beans:property name="serviceLocatorInterface" value="com.lich.IPhaseFactory"/>
</beans:bean>
在具体要使用IPhase的对象的类里面设置工厂bean
class PhaseBuilder {
@Inject
private IPhaseFactory phaseFactory;
IPhase build(String name) {
IPhase phase = phaseFactory.getPhase(name);//这里每次拿到的就是新的对象了
return phase;
}
看代码时这里有个困扰我的问题是 IPhaseFactory接口, 项目代码里面是没有实现类的, spring是在运行时动态代理生成了一个实现类, 那么这里就奇怪了,它怎么知道要用什么样的逻辑来返回我要的那个对象呢,比如 IPhase 接口下面有很多实现类,它怎么知道是哪一个呢?
看下ServiceLocatorFactoryBean类的源码就知道了
private Object invokeServiceLocatorMethod(Method method, Object[] args) throws Exception {
Class serviceLocatorMethodReturnType = getServiceLocatorMethodReturnType(method);
try {
String beanName = tryGetBeanName(args);
if (StringUtils.hasLength(beanName)) {
// Service locator for a specific bean name
return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
}
else {
// Service locator for a bean type
return beanFactory.getBean(serviceLocatorMethodReturnType);
}
}
}
private String tryGetBeanName(Object[] args) {
String beanName = "";
if (args != null && args.length == 1 && args[0] != null) {
beanName = args[0].toString();
}
// Look for explicit serviceId-to-beanName mappings.
if (serviceMappings != null) {
String mappedName = serviceMappings.getProperty(beanName);
if (mappedName != null) {
beanName = mappedName;
}
}
return beanName;
}
上面的代码中会测试着使用接口方法中的参数作为bean的name来去beanfactory里面找, 如果接口方法没有参数,
// Service locator for a specific bean name
return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
就会使用返回对象的类型来找
// Service locator for a bean type
return beanFactory.getBean(serviceLocatorMethodReturnType);
那么在我们的列子中就是 用参数中的name来找了
IPhase getPhase(String name);
比如下面的实现类
@Component("DataPersistPhase")
@Prototype
class DataPersistPhase implements IPhase