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的细节留待后面文章再讲述。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值