Skip to content

Commit

Permalink
feature: The data source proxy mode can be selected as AT or XA (apac…
Browse files Browse the repository at this point in the history
  • Loading branch information
wangliang181230 authored and hicf committed Nov 15, 2020
1 parent e9ab561 commit 82a28ff
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 15 deletions.
Expand Up @@ -508,4 +508,9 @@ public class ConfigurationKeys {
* The constant TX_SERVICE_GROUP.
*/
public static final String TX_SERVICE_GROUP = "txServiceGroup";

/**
* The constant DATA_SOURCE_PROXY_MODE.
*/
public static final String DATA_SOURCE_PROXY_MODE = "dataSourceProxyMode";
}
2 changes: 2 additions & 0 deletions core/src/main/java/io/seata/core/constants/DefaultValues.java
Expand Up @@ -80,6 +80,8 @@ public class DefaultValues {
public static final String DEFAULT_TC_CLUSTER = "default";
public static final String DEFAULT_GROUPLIST = "127.0.0.1:8091";

public static final String DEFAULT_DATA_SOURCE_PROXY_MODE = "AT";

public static final boolean DEFAULT_DISABLE_GLOBAL_TRANSACTION = false;

public static final int SERVER_DEFAULT_PORT = 8091;
Expand Down
10 changes: 8 additions & 2 deletions core/src/main/java/io/seata/core/context/RootContext.java
Expand Up @@ -19,6 +19,9 @@

import io.seata.common.exception.ShouldNeverHappenException;
import io.seata.common.util.StringUtils;
import io.seata.config.ConfigurationFactory;
import io.seata.core.constants.ConfigurationKeys;
import io.seata.core.constants.DefaultValues;
import io.seata.core.model.BranchType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -51,6 +54,9 @@ private RootContext() {

private static ContextCore CONTEXT_HOLDER = ContextCoreLoader.load();

private static final String DATA_SOURCE_PROXY_MODE = ConfigurationFactory.getInstance()
.getConfig(ConfigurationKeys.DATA_SOURCE_PROXY_MODE, DefaultValues.DEFAULT_DATA_SOURCE_PROXY_MODE);

/**
* Gets xid.
*
Expand Down Expand Up @@ -129,8 +135,8 @@ public static String getBranchType() {
if (StringUtils.isNotBlank(branchType)) {
return branchType;
}
//default branchType is AT
return BranchType.AT.name();
//default branchType is the dataSourceProxyMode
return BranchType.XA.name().equalsIgnoreCase(DATA_SOURCE_PROXY_MODE) ? BranchType.XA.name() : BranchType.AT.name();
}
return null;
}
Expand Down
1 change: 1 addition & 0 deletions script/client/spring/application.properties
Expand Up @@ -19,6 +19,7 @@ seata.excludes-for-auto-proxying=firstClassNameForExclude,secondClassNameForExcl
seata.application-id=applicationName
seata.tx-service-group=my_test_tx_group
seata.enable-auto-data-source-proxy=true
seata.data-source-proxy-mode=AT
seata.use-jdk-proxy=false
seata.client.rm.async-commit-buffer-limit=1000
seata.client.rm.report-retry-count=5
Expand Down
1 change: 1 addition & 0 deletions script/client/spring/application.yml
Expand Up @@ -3,6 +3,7 @@ seata:
application-id: applicationName
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: true
data-source-proxy-mode: AT
use-jdk-proxy: false
excludes-for-auto-proxying: firstClassNameForExclude,secondClassNameForExclude
client:
Expand Down
Expand Up @@ -71,6 +71,7 @@ public GlobalTransactionScanner globalTransactionScanner(SeataProperties seataPr
@ConditionalOnProperty(prefix = StarterConstants.SEATA_PREFIX, name = {"enableAutoDataSourceProxy", "enable-auto-data-source-proxy"}, havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean(SeataAutoDataSourceProxyCreator.class)
public SeataAutoDataSourceProxyCreator seataAutoDataSourceProxyCreator(SeataProperties seataProperties) {
return new SeataAutoDataSourceProxyCreator(seataProperties.isUseJdkProxy(),seataProperties.getExcludesForAutoProxying());
return new SeataAutoDataSourceProxyCreator(seataProperties.isUseJdkProxy(),
seataProperties.getExcludesForAutoProxying(), seataProperties.getDataSourceProxyMode());
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package io.seata.spring.boot.autoconfigure.properties;

import io.seata.core.constants.DefaultValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand Down Expand Up @@ -43,6 +44,10 @@ public class SeataProperties {
* Whether enable auto proxying of datasource bean
*/
private boolean enableAutoDataSourceProxy = true;
/**
* data source proxy mode
*/
private String dataSourceProxyMode = DefaultValues.DEFAULT_DATA_SOURCE_PROXY_MODE;
/**
* Whether use JDK proxy instead of CGLIB proxy
*/
Expand Down Expand Up @@ -97,6 +102,14 @@ public SeataProperties setEnableAutoDataSourceProxy(boolean enableAutoDataSource
return this;
}

public String getDataSourceProxyMode() {
return dataSourceProxyMode;
}

public void setDataSourceProxyMode(String dataSourceProxyMode) {
this.dataSourceProxyMode = dataSourceProxyMode;
}

public boolean isUseJdkProxy() {
return useJdkProxy;
}
Expand Down
@@ -0,0 +1,25 @@
{
"groups": [],
"properties": [
{
"name": "seata.data-source-proxy-mode",
"type": "java.lang.String",
"description": "data source proxy mode.",
"sourceType": "io.seata.spring.boot.autoconfigure.properties.SeataProperties",
"defaultValue": "AT"
}
],
"hints": [
{
"name": "seata.data-source-proxy-mode",
"values": [
{
"value": "AT"
},
{
"value": "XA"
}
]
}
]
}
Expand Up @@ -249,6 +249,7 @@ public void testSeataProperties() {
assertNull(context.getBean(SeataProperties.class).getApplicationId());
assertEquals("null-seata-service-group", context.getBean(SeataProperties.class).getTxServiceGroup());
assertTrue(context.getBean(SeataProperties.class).isEnableAutoDataSourceProxy());
assertEquals("AT", context.getBean(SeataProperties.class).getDataSourceProxyMode());
assertFalse(context.getBean(SeataProperties.class).isUseJdkProxy());

}
Expand Down
Expand Up @@ -21,24 +21,32 @@
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

import java.util.Map;

/**
* @author xingfudeshi@gmail.com
* The type auto data source proxy registrar
*/
public class AutoDataSourceProxyRegistrar implements ImportBeanDefinitionRegistrar {
private static final String ATTRIBUTE_KEY_USE_JDK_PROXY = "useJdkProxy";
private static final String ATTRIBUTE_KEY_EXCLUDES = "excludes";
private static final String ATTRIBUTE_KEY_DATA_SOURCE_PROXY_MODE = "dataSourceProxyMode";
public static final String BEAN_NAME_SEATA_AUTO_DATA_SOURCE_PROXY_CREATOR = "seataAutoDataSourceProxyCreator";

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(BEAN_NAME_SEATA_AUTO_DATA_SOURCE_PROXY_CREATOR)) {
boolean useJdkProxy = Boolean.parseBoolean(importingClassMetadata.getAnnotationAttributes(EnableAutoDataSourceProxy.class.getName()).get(ATTRIBUTE_KEY_USE_JDK_PROXY).toString());
String[] excludes = (String[]) importingClassMetadata.getAnnotationAttributes(EnableAutoDataSourceProxy.class.getName()).get(ATTRIBUTE_KEY_EXCLUDES);
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableAutoDataSourceProxy.class.getName());

boolean useJdkProxy = Boolean.parseBoolean(annotationAttributes.get(ATTRIBUTE_KEY_USE_JDK_PROXY).toString());
String[] excludes = (String[]) annotationAttributes.get(ATTRIBUTE_KEY_EXCLUDES);
String dataSourceProxyMode = (String) annotationAttributes.get(ATTRIBUTE_KEY_DATA_SOURCE_PROXY_MODE);

AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(SeataAutoDataSourceProxyCreator.class)
.addConstructorArgValue(useJdkProxy)
.addConstructorArgValue(excludes)
.addConstructorArgValue(dataSourceProxyMode)
.getBeanDefinition();
registry.registerBeanDefinition(BEAN_NAME_SEATA_AUTO_DATA_SOURCE_PROXY_CREATOR, beanDefinition);
}
Expand Down
Expand Up @@ -18,7 +18,9 @@
import javax.sql.DataSource;
import java.util.concurrent.ConcurrentHashMap;

import io.seata.core.model.BranchType;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.rm.datasource.xa.DataSourceProxyXA;

/**
* the type data source proxy holder
Expand All @@ -27,7 +29,7 @@
*/
public class DataSourceProxyHolder {
private static final int MAP_INITIAL_CAPACITY = 8;
private ConcurrentHashMap<DataSource, DataSourceProxy> dataSourceProxyMap;
private ConcurrentHashMap<DataSource, DataSource> dataSourceProxyMap;

private DataSourceProxyHolder() {
dataSourceProxyMap = new ConcurrentHashMap<>(MAP_INITIAL_CAPACITY);
Expand Down Expand Up @@ -57,11 +59,13 @@ public static DataSourceProxyHolder get() {
/**
* Put dataSource
*
* @param dataSource
* @param originalDataSource the original data source
* @param dataSourceProxyMode the data source proxy mode
* @return dataSourceProxy
*/
public DataSourceProxy putDataSource(DataSource dataSource) {
return this.dataSourceProxyMap.computeIfAbsent(dataSource, DataSourceProxy::new);
public DataSource putDataSource(DataSource originalDataSource, String dataSourceProxyMode) {
return this.dataSourceProxyMap.computeIfAbsent(originalDataSource,
BranchType.XA.name().equalsIgnoreCase(dataSourceProxyMode) ? DataSourceProxyXA::new : DataSourceProxy::new);
}

/**
Expand All @@ -70,7 +74,7 @@ public DataSourceProxy putDataSource(DataSource dataSource) {
* @param dataSource
* @return dataSourceProxy
*/
public DataSourceProxy getDataSourceProxy(DataSource dataSource) {
public DataSource getDataSourceProxy(DataSource dataSource) {
return this.dataSourceProxyMap.get(dataSource);
}

Expand Down
Expand Up @@ -42,7 +42,14 @@
/**
* Specifies which datasource bean are not eligible for auto-proxying
*
* @return
* @return excludes
*/
String[] excludes() default {};

/**
* Data source proxy mode, AT or XA
*
* @return dataSourceProxyMode
*/
String dataSourceProxyMode() default "AT";
}
Expand Up @@ -18,7 +18,9 @@
import javax.sql.DataSource;
import java.lang.reflect.Method;

import io.seata.core.model.BranchType;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.rm.datasource.xa.DataSourceProxyXA;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.IntroductionInfo;
Expand All @@ -29,12 +31,21 @@
*/
public class SeataAutoDataSourceProxyAdvice implements MethodInterceptor, IntroductionInfo {

private final String dataSourceProxyMode;
private final Class<? extends DataSource> dataSourceProxyClazz;

public SeataAutoDataSourceProxyAdvice(String dataSourceProxyMode) {
this.dataSourceProxyMode = dataSourceProxyMode;
this.dataSourceProxyClazz = BranchType.XA.name().equalsIgnoreCase(dataSourceProxyMode) ?
DataSourceProxyXA.class : DataSourceProxy.class;
}

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
DataSourceProxy dataSourceProxy = DataSourceProxyHolder.get().putDataSource((DataSource) invocation.getThis());
DataSource dataSourceProxy = DataSourceProxyHolder.get().putDataSource((DataSource) invocation.getThis(), dataSourceProxyMode);
Method method = invocation.getMethod();
Object[] args = invocation.getArguments();
Method m = BeanUtils.findDeclaredMethod(DataSourceProxy.class, method.getName(), method.getParameterTypes());
Method m = BeanUtils.findDeclaredMethod(dataSourceProxyClazz, method.getName(), method.getParameterTypes());
if (m != null) {
return m.invoke(dataSourceProxy, args);
} else {
Expand Down
Expand Up @@ -32,10 +32,11 @@
public class SeataAutoDataSourceProxyCreator extends AbstractAutoProxyCreator {
private static final Logger LOGGER = LoggerFactory.getLogger(SeataAutoDataSourceProxyCreator.class);
private final String[] excludes;
private final Advisor advisor = new DefaultIntroductionAdvisor(new SeataAutoDataSourceProxyAdvice());
private final Advisor advisor;

public SeataAutoDataSourceProxyCreator(boolean useJdkProxy, String[] excludes) {
public SeataAutoDataSourceProxyCreator(boolean useJdkProxy, String[] excludes, String dataSourceProxyMode) {
this.excludes = excludes;
this.advisor = new DefaultIntroductionAdvisor(new SeataAutoDataSourceProxyAdvice(dataSourceProxyMode));
setProxyTargetClass(!useJdkProxy);
}

Expand Down

0 comments on commit 82a28ff

Please sign in to comment.