看源碼多了,從一開始看別人怎麼實現,逐漸變成了喜歡研究別人設計的架構,看看別人的思路。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的細節留待後面文章再講述。