Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: The data source proxy mode can be selected as AT or XA #2913

Merged
merged 12 commits into from Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
wangliang181230 marked this conversation as resolved.
Show resolved Hide resolved
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