activiti學習(十三)——activiti數據庫存儲(二)——SessionFactory架構與抽象工廠模式

看源碼多了,從一開始看別人怎麼實現,逐漸變成了喜歡研究別人設計的架構,看看別人的思路。activiti中使用了很多不同的設計模式,值得各位學習,日後用在自己的項目中,當然對這方面不感興趣的請略過。本文主要是針對《activiti學習(十二)——activiti數據庫存儲(一)——數據連接初始化與mybatis封裝》裏面SessionFactory的架構進行分析。在那篇文章中,說SessionFactory使用抽象工廠創建實體對應的實體管理類。

抽象工廠模式

先介紹一下抽象工廠模式。這個模式隨便網上一搜就能搜到相關的概念。這裏通俗一點講,抽象工廠就是工廠方法的升級版。工廠方法是通過傳入不同參數去生成不同類型的實例,那抽象工廠就是通過傳入不同的參數去生成不同的工廠類,然後再通過工廠類去生成實例。接下來寫一個簡單的例子:

首先我們創建一個產品的接口Product.java,以及幾個具體類。

public interface Product {

	public void showName();
}
public class Cpu implements Product{

	@Override
	public void showName() {
		System.out.println("Cpu");
	}
}
public class Memory implements Product{

	@Override
	public void showName() {
		System.out.println("Memory");
	}
}
public class Bus implements Product{

	@Override
	public void showName() {
		System.out.println("Bus");
	}
}
public class Car implements Product{

	@Override
	public void showName() {
		System.out.println("Car");
	}
}

創建了Cpu、Memory、Bus、Car四個實現了Product接口的類。它們功能都很簡單,只有showName方法。

創建抽象工廠類AbstractFactory.class

public abstract class AbstractFactory {
	public abstract Product produce(String productName) throws Exception;
}

只給了抽象工廠類一個produce的函數,根據產品名稱進行生產。

接着構建兩個具體的工廠類,負責生產設備的DeviceFactory和生產汽車的VehicleFactory

public class DeviceFactory extends AbstractFactory{

	@Override
	public Product produce(String productName) throws Exception {
		if("CPU".equals(productName)) {
			return new Cpu();
		}else if("Memory".equals(productName)) {
			return new Memory();
		}else {
			return null;
		}
	}
}
public class VehicleFactory extends AbstractFactory{

	@Override
	public Product produce(String productName) throws Exception {
		if("Car".equals(productName)) {
			return new Car();
		}else if("Bus".equals(productName)) {
			return new Bus();
		}else {
			return null;
		}
	}
}

從上面兩個工廠可以看到,根據傳入的productName不同,將會新建不同的類。

我們還需要一個創建工廠類的方法,構建FactoryProvider.java:

public class FactoryProvider {

	public static AbstractFactory getFactory(Class<? extends AbstractFactory> clazz) throws Exception{
		return clazz.newInstance();
	}
}

getFactory靜態方法通過java反射的方式,根據傳入的類型創建對應的類。

下來我們編寫客戶端Client:

public class Client {

	public static void main(String[] args) throws Exception {
		AbstractFactory computerFactory = FactoryProvider.getFactory(DeviceFactory.class);
		AbstractFactory vehicleFactory = FactoryProvider.getFactory(VehicleFactory.class);
		Product cpu = computerFactory.produce("CPU");
		Product memory = computerFactory.produce("Memory");
		Product car = vehicleFactory.produce("Car");
		Product bus = vehicleFactory.produce("Bus");
		cpu.showName();
		memory.showName();
		car.showName();
		bus.showName();
	}
}

第4-5行通過傳入不同的class類型,可以獲得具體的工廠,6-9行是工廠方法,分別通過設備工廠創建cpu和內容,通過汽車工廠創建小車和公交車。

上面這個例子是比較簡單的例子,並不完善,實際項目中的調用也沒有那麼直白。上述代碼大致的架構如下:

 

SessionFactory架構

上圖是SessionFactory的大致架構。 SessionFactory屬於抽象工廠,聲明的getSessionType用於返回具體工廠類型的class。openSession用於創建並返回具體的實體管理類。XXXManageFactory就是具體的工廠類。Session接口聲明的flush方法用於把增刪改操作從緩存刷新到數據庫,close爲關閉連接的清理工作。

AbstractManager定義了insert、delete等方法,調用DbSqlSession,增刪改的對象放入緩存中,待命令執行結束後刷新到數據庫。AbstractManager.java:

public abstract class AbstractManager implements Session {
  
  public void insert(PersistentObject persistentObject) {
    getDbSqlSession().insert(persistentObject);
  }
  public void delete(PersistentObject persistentObject) {
    getDbSqlSession().delete(persistentObject);
  }
  protected DbSqlSession getDbSqlSession() {
    return getSession(DbSqlSession.class);
  }
  protected <T> T getSession(Class<T> sessionClass) {
    return Context.getCommandContext().getSession(sessionClass);
  }
  protected DeploymentEntityManager getDeploymentManager() {
    return getSession(DeploymentEntityManager.class);
  }
  protected ResourceEntityManager getResourceManager() {
    return getSession(ResourceEntityManager.class);
  }
  
//......獲取各個實體管理類
  
  protected ProcessEngineConfigurationImpl getProcessEngineConfiguration() {
  	return Context.getProcessEngineConfiguration();
  }
  public void close() {
  }
  public void flush() {
  }
}

上面getXXXManager方法調用getSession,即調用13行的CommandContext的getSession方法。查看CommandContext.java:

public <T> T getSession(Class<T> sessionClass) {
  Session session = sessions.get(sessionClass);
  if (session == null) {
    SessionFactory sessionFactory = sessionFactories.get(sessionClass);
    if (sessionFactory==null) {
      throw new ActivitiException("no session factory configured for "+sessionClass.getName());
    }
    session = sessionFactory.openSession();
    sessions.put(sessionClass, session);
  }

  return (T) session;
}

第4行先從初始化sessionFactory時添加到sessionFactories中的工廠類中獲取具體工廠類,第8行openSession創建具體的實體管理類,即XXXEntityManager。

XXXEntityManager類是給用戶與數據庫交互的接口,我們以比較簡單的EventLogEntryEntityManager.java爲例:

public class EventLogEntryEntityManager extends AbstractManager {
  
  public void insert(EventLogEntryEntity eventLogEntryEntity) {
  	getDbSqlSession().insert(eventLogEntryEntity);
  }
  
  @SuppressWarnings("unchecked")
  public List<EventLogEntry> findAllEventLogEntries() {
  	return getDbSqlSession().selectList("selectAllEventLogEntries");
  }
  
  @SuppressWarnings("unchecked")
  public List<EventLogEntry> findEventLogEntries(long startLogNr, long pageSize) {
  	Map<String, Object> params = new HashMap<String, Object>(2);
  	params.put("startLogNr", startLogNr);
  	if (pageSize > 0) {
  		params.put("endLogNr", startLogNr + pageSize + 1);
  	}
  	return getDbSqlSession().selectList("selectEventLogEntries", params);
  }
  
  @SuppressWarnings("unchecked")
  public List<EventLogEntry> findEventLogEntriesByProcessInstanceId(String processInstanceId) {
    Map<String, Object> params = new HashMap<String, Object>(2);
    params.put("processInstanceId", processInstanceId);
    return getDbSqlSession().selectList("selectEventLogEntriesByProcessInstanceId", params);
  }
  
  public void deleteEventLogEntry(long logNr) {
  	getDbSqlSession().getSqlSession().delete("deleteEventLogEntry", logNr);
  }
   
}

從上面的方法可以看到,這些提供給用戶的接口方法,都是設置變量,然後通過DbSqlSession的方法,最終調用mybaits。調用mybatis的細節留待後面文章再講述。

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