Flowable源码地址:https://github.com/flowable/flowable-engine
AbstractEngineConfiguration引擎配置抽象类
public abstract class AbstractEngineConfiguration {
protected final Logger logger = LoggerFactory.getLogger(getClass());
/** 表示“无租户”的租户id */
public static final String NO_TENANT_ID = "";
/**
* 在创建表单引擎时,对照库检查DB模式的版本,如果版本不匹配,则引发异常。
*/
public static final String DB_SCHEMA_UPDATE_FALSE = "false";
public static final String DB_SCHEMA_UPDATE_CREATE = "create";
public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";
/**
* 在创建表单引擎时创建模式,在关闭表单引擎时删除模式.
*/
public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create";
/**
* 构建流程引擎后,将执行检查,并在必要时更新模式.
*/
public static final String DB_SCHEMA_UPDATE_TRUE = "true";
protected boolean forceCloseMybatisConnectionPool = true;
protected String databaseType;
protected String jdbcDriver = "org.h2.Driver";
protected String jdbcUrl = "jdbc:h2:tcp://localhost/~/flowable";
protected String jdbcUsername = "sa";
protected String jdbcPassword = "";
protected String dataSourceJndiName;
protected int jdbcMaxActiveConnections = 16;
protected int jdbcMaxIdleConnections = 8;
protected int jdbcMaxCheckoutTime;
protected int jdbcMaxWaitTime;
protected boolean jdbcPingEnabled;
protected String jdbcPingQuery;
protected int jdbcPingConnectionNotUsedFor;
protected int jdbcDefaultTransactionIsolationLevel;
protected DataSource dataSource;
protected SchemaManager commonSchemaManager;
protected SchemaManager schemaManager;
protected Command<Void> schemaManagementCmd;
protected String databaseSchemaUpdate = DB_SCHEMA_UPDATE_FALSE;
/**
* 执行数据库模式创建或更新操作时是否使用锁.
*/
protected boolean useLockForDatabaseSchemaUpdate = false;
protected String xmlEncoding = "UTF-8";
// 命令执行器 ///
protected CommandExecutor commandExecutor;
protected Collection<? extends CommandInterceptor> defaultCommandInterceptors;
protected CommandConfig defaultCommandConfig;
protected CommandConfig schemaCommandConfig;
protected CommandContextFactory commandContextFactory;
protected CommandInterceptor commandInvoker;
protected AgendaOperationRunner agendaOperationRunner = (commandContext, runnable) -> runnable.run();
protected List<CommandInterceptor> customPreCommandInterceptors;
protected List<CommandInterceptor> customPostCommandInterceptors;
protected List<CommandInterceptor> commandInterceptors;
protected Map<String, AbstractEngineConfiguration> engineConfigurations = new HashMap<>();
protected Map<String, AbstractServiceConfiguration> serviceConfigurations = new HashMap<>();
protected ClassLoader classLoader;
/**
* 使用Clas.forname方法或者ClassLoader.loadClass方法加载类。查看http://forums.activiti.org/content/reflectutilloadclass-and-custom- classloader
*/
protected boolean useClassForNameClassLoading = true;
protected List<EngineLifecycleListener> engineLifecycleListeners;
// 事件注册 //
protected Map<String, EventRegistryEventConsumer> eventRegistryEventConsumers = new HashMap<>();
// MYBATIS SQL SESSION 工厂 /
protected boolean isDbHistoryUsed = true;
protected DbSqlSessionFactory dbSqlSessionFactory;
protected SqlSessionFactory sqlSessionFactory;
protected TransactionFactory transactionFactory;
protected TransactionContextFactory transactionContextFactory;
/**
* 如果设置为true,则启用批量插入(将sql插入分组在一起)。默认为true.
* 对于某些数据库(例如DB2+z/OS),需要将其设置为false.
*/
protected boolean isBulkInsertEnabled = true;
/**
* 一些数据库对一条sql insert的参数有限制(例如sql Server,最多2000个参数(不等于插入语句))。如果异常很多时,请调整此参数
* 放入到一个大容量插入中,或者如果数据库能够处理,并且有大量数据需要插入,则将其提高.
* 默认情况下:100(mssql server为55,因为它在语句中有2000个参数的硬限制)
*/
protected int maxNrOfStatementsInBulkInsert = 100;
public int DEFAULT_MAX_NR_OF_STATEMENTS_BULK_INSERT_SQL_SERVER = 55; // 目前执行的参数最多(35). 2000 / 35 = 57.
protected String mybatisMappingFile;
protected Set<Class<?>> customMybatisMappers;
protected Set<String> customMybatisXMLMappers;
protected List<Interceptor> customMybatisInterceptors;
protected Set<String> dependentEngineMyBatisXmlMappers;
protected List<MybatisTypeAliasConfigurator> dependentEngineMybatisTypeAliasConfigs;
protected List<MybatisTypeHandlerConfigurator> dependentEngineMybatisTypeHandlerConfigs;
// SESSION 工厂 ///
protected List<SessionFactory> customSessionFactories;
protected Map<Class<?>, SessionFactory> sessionFactories;
protected boolean enableEventDispatcher = true;
protected FlowableEventDispatcher eventDispatcher;
protected List<FlowableEventListener> eventListeners;
protected Map<String, List<FlowableEventListener>> typedEventListeners;
protected List<EventDispatchAction> additionalEventDispatchActions;
protected LoggingListener loggingListener;
protected boolean transactionsExternallyManaged;
/**
* 使用可设置为配置或不配置关系数据库的标志。这对于完全不使用关系数据库的自定义实现非常有用.
*
* 如果为true(默认值),将使用{@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()}值来确定数据库模式需要执行的操作.
*
* 如果为false,则不会进行验证或模式创建。这意味着之前必须“手动”创建数据库模式,但引擎不会验证该模式是否正确。将不使用{@link AbstractEngineConfiguration#getDatabaseSchemaUpdate()}值.
*/
protected boolean usingRelationalDatabase = true;
/**
* 可设置为配置是否使用模式的标志。这对于完全不使用关系数据库的自定义实现非常有用.
* 将{@link#usingRelationalDatabase}设置为true将自动意味着使用模式.
*/
protected boolean usingSchemaMgmt = true;
/**
*允许配置用于process engine所有运行时操作的数据库表前缀。例如,如果指定一个名为“PRE1”的前缀,Flowable将通过'PRE1.ACT_RU_EXECUTION_'表查询执行情况.
*
* 注意:自动数据库模式管理不考虑前缀。如果使用{@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_CREATE_DROP}或{@link AbstractEngineConfiguration#DB_SCHEMA_UPDATE_TRUE},Flowable将使用默认名称创建数据库表,而不考虑此处配置的前缀.
*/
protected String databaseTablePrefix = "";
/**
* 用于进行通配符搜索的转义字符.
*
* 这将添加到包含LIKE子句查询的末尾。例如:SELECT * FROM table WHERE column LIKE '%\%%' 的转义符'\';
*/
protected String databaseWildcardEscapeCharacter;
/**
* 要使用的数据库目录
*/
protected String databaseCatalog = "";
/**
* 在某些情况下,如果数据库元数据没有正确返回,您需要设置用于表检查/生成的模式, 查看 https://jira.codehaus.org/browse/ACT-1220,
* https://jira.codehaus.org/browse/ACT-1062
*/
protected String databaseSchema;
/**
* 如果定义的databaseTablePrefix是模式名,而不是实际的表名前缀,则设置为true。这与检查是否存在Flowable表(databaseTablePrefix)有关。如果已经考虑了模式,就不会再使用-,为表检查添加前缀将导致错误的表名.
*/
protected boolean tablePrefixIsSchema;
/**
* 如果最新版本的定义可被恢复,则设置为true,忽略可能的父级部署ID值
*/
protected boolean alwaysLookupLatestDefinitionVersion;
/**
* 默认查找应退回到默认租户,则设置为true(默认情况下为空字符串或定义的租户值)
*/
protected boolean fallbackToDefaultTenant;
/**
* 默认租户提供程序,在全局或本地回退到默认租户值为true的情况下,在查找定义时执行
*/
protected DefaultTenantProvider defaultTenantProvider = (tenantId, scope, scopeKey) -> NO_TENANT_ID;
/**
* 启用记录sql语句执行时间的MyBatis插件.
*/
protected boolean enableLogSqlExecutionTime;
protected Properties databaseTypeMappings = getDefaultDatabaseTypeMappings();
/**
* 获取锁时检查之间的持续时间.
*/
protected Duration lockPollRate = Duration.ofSeconds(10);
/**
* 在放弃之前等待DB模式锁定的持续时间.
*/
protected Duration schemaLockWaitTime = Duration.ofMinutes(5);
// 数据管理器 //
protected PropertyDataManager propertyDataManager;
protected ByteArrayDataManager byteArrayDataManager;
protected TableDataManager tableDataManager;
// 实体管理器
protected PropertyEntityManager propertyEntityManager;
protected ByteArrayEntityManager byteArrayEntityManager;
protected List<EngineDeployer> customPreDeployers;
protected List<EngineDeployer> customPostDeployers;
protected List<EngineDeployer> deployers;
// 配置程序
protected boolean enableConfiguratorServiceLoader = true; // 默认情况下启用。在某些环境中,这应该设置为false(例如osgi)
protected List<EngineConfigurator> configurators; // 注入式配置器
protected List<EngineConfigurator> allConfigurators; // 包括自动发现的配置程序
protected EngineConfigurator idmEngineConfigurator;
protected EngineConfigurator eventRegistryConfigurator;
public static final String PRODUCT_NAME_POSTGRES = "PostgreSQL";
public static final String PRODUCT_NAME_CRDB = "CockroachDB";
public static final String DATABASE_TYPE_H2 = "h2";
public static final String DATABASE_TYPE_HSQL = "hsql";
public static final String DATABASE_TYPE_MYSQL = "mysql";
public static final String DATABASE_TYPE_ORACLE = "oracle";
public static final String DATABASE_TYPE_POSTGRES = "postgres";
public static final String DATABASE_TYPE_MSSQL = "mssql";
public static final String DATABASE_TYPE_DB2 = "db2";
public static final String DATABASE_TYPE_COCKROACHDB = "cockroachdb";
public static Properties getDefaultDatabaseTypeMappings() {
Properties databaseTypeMappings = new Properties();
databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2);
databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL);
databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL);
databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL);
databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE);
databaseTypeMappings.setProperty(PRODUCT_NAME_POSTGRES, DATABASE_TYPE_POSTGRES);
databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL);
databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty(PRODUCT_NAME_CRDB, DATABASE_TYPE_COCKROACHDB);
return databaseTypeMappings;
}
protected Map<Object, Object> beans;
protected IdGenerator idGenerator;
protected boolean usePrefixId;
protected Clock clock;
protected ObjectMapper objectMapper;
// 变量
public static final int DEFAULT_GENERIC_MAX_LENGTH_STRING = 4000;
public static final int DEFAULT_ORACLE_MAX_LENGTH_STRING = 2000;
/**
* 定义在数据库中存储字符串变量类型的最大长度。主要用于Oracle NVARCHAR2 2000个字符的限制
*/
protected int maxLengthStringVariableType = -1;
protected void initEngineConfigurations() {
addEngineConfiguration(getEngineCfgKey(), getEngineScopeType(), this);
}
// 数据源
// ///
protected void initDataSource() {
if (dataSource == null) {
if (dataSourceJndiName != null) {
try {
dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName);
} catch (Exception e) {
throw new FlowableException("couldn't lookup datasource from " + dataSourceJndiName + ": " + e.getMessage(), e);
}
} else if (jdbcUrl != null) {
if ((jdbcDriver == null) || (jdbcUsername == null)) {
throw new FlowableException("DataSource or JDBC properties have to be specified in a process engine configuration");
}
logger.debug("initializing datasource to db: {}", jdbcUrl);
if (logger.isInfoEnabled()) {
logger.info("Configuring Datasource with following properties (omitted password for security)");
logger.info("datasource driver : {}", jdbcDriver);
logger.info("datasource url : {}", jdbcUrl);
logger.info("datasource user name : {}", jdbcUsername);
}
PooledDataSource pooledDataSource = new PooledDataSource(this.getClass().getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword);
if (jdbcMaxActiveConnections > 0) {
pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections);
}
if (jdbcMaxIdleConnections > 0) {
pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections);
}
if (jdbcMaxCheckoutTime > 0) {
pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime);
}
if (jdbcMaxWaitTime > 0) {
pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime);
}
if (jdbcPingEnabled) {
pooledDataSource.setPoolPingEnabled(true);
if (jdbcPingQuery != null) {
pooledDataSource.setPoolPingQuery(jdbcPingQuery);
}
pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor);
}
if (jdbcDefaultTransactionIsolationLevel > 0) {
pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel);
}
dataSource = pooledDataSource;
}
}
if (databaseType == null) {
initDatabaseType();
}
}
public void initDatabaseType() {
Connection connection = null;
try {
connection = dataSource.getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
String databaseProductName = databaseMetaData.getDatabaseProductName();
logger.debug("database product name: '{}'", databaseProductName);
// CRDB不会通过jdbc驱动程序公开这个版本,所以我们需要通过version()获取它.
if (PRODUCT_NAME_POSTGRES.equalsIgnoreCase(databaseProductName)) {
try (PreparedStatement preparedStatement = connection.prepareStatement("select version() as version;");
ResultSet resultSet = preparedStatement.executeQuery()) {
String version = null;
if (resultSet.next()) {
version = resultSet.getString("version");
}
if (StringUtils.isNotEmpty(version) && version.toLowerCase().startsWith(PRODUCT_NAME_CRDB.toLowerCase())) {
databaseProductName = PRODUCT_NAME_CRDB;
logger.info("CockroachDB version '{}' detected", version);
}
}