看源码多了,从一开始看别人怎么实现,逐渐变成了喜欢研究别人设计的架构,看看别人的思路。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的细节留待后面文章再讲述。