ServiceLocatorFactoryBean 学习
今天看一个新项目的代码, 对里面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