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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章