给flowable动态设置目标数据源。
在创建 SpringProcessEngineConfiguration 的时候,默认引入了spring中的DataSource
(1)创建SpringProcessEngineConfiguration
@Bean
@ConditionalOnMissingBean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(DataSource dataSource, PlatformTransactionManager platformTransactionManager,
@Process ObjectProvider<IdGenerator> processIdGenerator,
ObjectProvider<IdGenerator> globalIdGenerator,
@ProcessAsync ObjectProvider<AsyncExecutor> asyncExecutorProvider,
@ProcessAsyncHistory ObjectProvider<AsyncExecutor> asyncHistoryExecutorProvider,
ObjectProvider<List<AutoDeploymentStrategy<ProcessEngine>>> processEngineAutoDeploymentStrategies) throws IOException {
,,,,,,
configureEngine(conf, dataSource);
......
}
(2) configureEngine(conf, dataSource);
protected void configureEngine(AbstractEngineConfiguration engineConfiguration, DataSource dataSource) {
engineConfiguration.setDataSource(dataSource);
}
@Override
public ProcessEngineConfiguration setDataSource(DataSource dataSource) {
if (dataSource instanceof TransactionAwareDataSourceProxy) {
return super.setDataSource(dataSource);
} else {
// Wrap datasource in Transaction-aware proxy
DataSource proxiedDataSource = new TransactionAwareDataSourceProxy(dataSource);
return super.setDataSource(proxiedDataSource);
}
}
最终将这个 dataSource 设置到了 targetDataSource
public void setTargetDataSource(@Nullable DataSource targetDataSource) {
this.targetDataSource = targetDataSource;
}
通过实现 EngineConfigurator 接口
public class CustomEngineConfigurator implements EngineConfigurator {
@Override
public void beforeInit(AbstractEngineConfiguration engineConfiguration) {
DataSource dataSource = engineConfiguration.getDataSource();
if (dataSource instanceof TransactionAwareDataSourceProxy) {
TransactionAwareDataSourceProxy proxy = (TransactionAwareDataSourceProxy) dataSource;
DataSource targetDataSource = proxy.getTargetDataSource();
if (targetDataSource instanceof DynamicDataSource) {
DynamicDataSource dynamicDataSource = (DynamicDataSource) targetDataSource;
DataSource resolvedDefaultDataSource = dynamicDataSource.getResolvedDefaultDataSource();
if (resolvedDefaultDataSource != null) {
//修改数据源
engineConfiguration.setDataSource(resolvedDefaultDataSource);
}
}
}
}
@Override
public void configure(AbstractEngineConfiguration engineConfiguration) {
}
@Override
public int getPriority() {
return 0;
}
}
(1)获取连接
TransactionAwareDataSourceProxy.java
@Override
public Connection getConnection() throws SQLException {
return getTransactionAwareConnectionProxy(obtainTargetDataSource());
}
@Override
public Connection getConnection() throws SQLException {
return getTransactionAwareConnectionProxy(obtainTargetDataSource());
}
通过obtainTargetDataSource()获取上面设置的默认数据源
通过getTransactionAwareConnectionProxy获取数据源代理对象,回调是 TransactionAwareInvocationHandler
protected Connection getTransactionAwareConnectionProxy(DataSource targetDataSource) {
return (Connection) Proxy.newProxyInstance(
ConnectionProxy.class.getClassLoader(),
new Class<?>[] {ConnectionProxy.class},
new TransactionAwareInvocationHandler(targetDataSource));
}
(2)TransactionAwareInvocationHandler
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on ConnectionProxy interface coming in...
......
if (this.target == null) {
if (method.getName().equals("getWarnings") || method.getName().equals("clearWarnings")) {
// Avoid creation of target Connection on pre-close cleanup (e.g. Hibernate Session)
return null;
}
if (this.closed) {
throw new SQLException("Connection handle already closed");
}
//根据 targetDataSource 获取目标数据源,这里就获取到了通过 EngineConfigurator 接口实现类设置的数据源
if (shouldObtainFixedConnection(this.targetDataSource)) {
this.target = DataSourceUtils.doGetConnection(this.targetDataSource);
}
}
Connection actualTarget = this.target;
if (actualTarget == null) {
actualTarget = DataSourceUtils.doGetConnection(this.targetDataSource);
}
if (method.getName().equals("getTargetConnection")) {
// Handle getTargetConnection method: return underlying Connection.
return actualTarget;
}
// Invoke method on target Connection.
try {
Object retVal = method.invoke(actualTarget, args);
// If return value is a Statement, apply transaction timeout.
// Applies to createStatement, prepareStatement, prepareCall.
if (retVal instanceof Statement) {
DataSourceUtils.applyTransactionTimeout((Statement) retVal, this.targetDataSource);
}
return retVal;
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
finally {
if (actualTarget != this.target) {
DataSourceUtils.doReleaseConnection(actualTarget, this.targetDataSource);
}
}
}
}
可以通过 EngineConfigurator 接口回调给flowable设置默认的数据源,
当然在获取连接的时候还需要考虑事务,因为在DataSourceUtils.doGetConnection(this.targetDataSource);这一步可能获取到目标数据源连接,也可能从事务中获取。