Commit 8835836f4e71205b2015905e4d6d074f20f266f1

Authored by 徐烜
0 parents

tcc-transaction-1.1.5 注释版,版权是原作者的

Showing 99 changed files with 3293 additions and 0 deletions
.gitignore 0 → 100644
  1 +++ a/.gitignore
  1 +.classpath
  2 +.project
  3 +.springBeans
  4 +.settings/*
  5 +/target/*
  6 +node_modules/
  7 +test_junitReport/
  8 +test_coverage/
  9 +.idea
  10 +.DS_Store
  11 +*.iml
  12 +tmp
  13 +
  14 +# git忽略空文件夹,按照惯例,空文件夹下放置.gitkeep文件避免文件夹被忽略不上传。
  15 +!.gitkeep
  16 +/target/
... ...
LICENSE.txt 0 → 100755
  1 +++ a/LICENSE.txt
  1 + Apache License
  2 + Version 2.0, January 2004
  3 + http://www.apache.org/licenses/
  4 +
  5 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
  6 +
  7 + 1. Definitions.
  8 +
  9 + "License" shall mean the terms and conditions for use, reproduction,
  10 + and distribution as defined by Sections 1 through 9 of this document.
  11 +
  12 + "Licensor" shall mean the copyright owner or entity authorized by
  13 + the copyright owner that is granting the License.
  14 +
  15 + "Legal Entity" shall mean the union of the acting entity and all
  16 + other entities that control, are controlled by, or are under common
  17 + control with that entity. For the purposes of this definition,
  18 + "control" means (i) the power, direct or indirect, to cause the
  19 + direction or management of such entity, whether by contract or
  20 + otherwise, or (ii) ownership of fifty percent (50%) or more of the
  21 + outstanding shares, or (iii) beneficial ownership of such entity.
  22 +
  23 + "You" (or "Your") shall mean an individual or Legal Entity
  24 + exercising permissions granted by this License.
  25 +
  26 + "Source" form shall mean the preferred form for making modifications,
  27 + including but not limited to software source code, documentation
  28 + source, and configuration files.
  29 +
  30 + "Object" form shall mean any form resulting from mechanical
  31 + transformation or translation of a Source form, including but
  32 + not limited to compiled object code, generated documentation,
  33 + and conversions to other media types.
  34 +
  35 + "Work" shall mean the work of authorship, whether in Source or
  36 + Object form, made available under the License, as indicated by a
  37 + copyright notice that is included in or attached to the work
  38 + (an example is provided in the Appendix below).
  39 +
  40 + "Derivative Works" shall mean any work, whether in Source or Object
  41 + form, that is based on (or derived from) the Work and for which the
  42 + editorial revisions, annotations, elaborations, or other modifications
  43 + represent, as a whole, an original work of authorship. For the purposes
  44 + of this License, Derivative Works shall not include works that remain
  45 + separable from, or merely link (or bind by name) to the interfaces of,
  46 + the Work and Derivative Works thereof.
  47 +
  48 + "Contribution" shall mean any work of authorship, including
  49 + the original version of the Work and any modifications or additions
  50 + to that Work or Derivative Works thereof, that is intentionally
  51 + submitted to Licensor for inclusion in the Work by the copyright owner
  52 + or by an individual or Legal Entity authorized to submit on behalf of
  53 + the copyright owner. For the purposes of this definition, "submitted"
  54 + means any form of electronic, verbal, or written communication sent
  55 + to the Licensor or its representatives, including but not limited to
  56 + communication on electronic mailing lists, source code control systems,
  57 + and issue tracking systems that are managed by, or on behalf of, the
  58 + Licensor for the purpose of discussing and improving the Work, but
  59 + excluding communication that is conspicuously marked or otherwise
  60 + designated in writing by the copyright owner as "Not a Contribution."
  61 +
  62 + "Contributor" shall mean Licensor and any individual or Legal Entity
  63 + on behalf of whom a Contribution has been received by Licensor and
  64 + subsequently incorporated within the Work.
  65 +
  66 + 2. Grant of Copyright License. Subject to the terms and conditions of
  67 + this License, each Contributor hereby grants to You a perpetual,
  68 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  69 + copyright license to reproduce, prepare Derivative Works of,
  70 + publicly display, publicly perform, sublicense, and distribute the
  71 + Work and such Derivative Works in Source or Object form.
  72 +
  73 + 3. Grant of Patent License. Subject to the terms and conditions of
  74 + this License, each Contributor hereby grants to You a perpetual,
  75 + worldwide, non-exclusive, no-charge, royalty-free, irrevocable
  76 + (except as stated in this section) patent license to make, have made,
  77 + use, offer to sell, sell, import, and otherwise transfer the Work,
  78 + where such license applies only to those patent claims licensable
  79 + by such Contributor that are necessarily infringed by their
  80 + Contribution(s) alone or by combination of their Contribution(s)
  81 + with the Work to which such Contribution(s) was submitted. If You
  82 + institute patent litigation against any entity (including a
  83 + cross-claim or counterclaim in a lawsuit) alleging that the Work
  84 + or a Contribution incorporated within the Work constitutes direct
  85 + or contributory patent infringement, then any patent licenses
  86 + granted to You under this License for that Work shall terminate
  87 + as of the date such litigation is filed.
  88 +
  89 + 4. Redistribution. You may reproduce and distribute copies of the
  90 + Work or Derivative Works thereof in any medium, with or without
  91 + modifications, and in Source or Object form, provided that You
  92 + meet the following conditions:
  93 +
  94 + (a) You must give any other recipients of the Work or
  95 + Derivative Works a copy of this License; and
  96 +
  97 + (b) You must cause any modified files to carry prominent notices
  98 + stating that You changed the files; and
  99 +
  100 + (c) You must retain, in the Source form of any Derivative Works
  101 + that You distribute, all copyright, patent, trademark, and
  102 + attribution notices from the Source form of the Work,
  103 + excluding those notices that do not pertain to any part of
  104 + the Derivative Works; and
  105 +
  106 + (d) If the Work includes a "NOTICE" text file as part of its
  107 + distribution, then any Derivative Works that You distribute must
  108 + include a readable copy of the attribution notices contained
  109 + within such NOTICE file, excluding those notices that do not
  110 + pertain to any part of the Derivative Works, in at least one
  111 + of the following places: within a NOTICE text file distributed
  112 + as part of the Derivative Works; within the Source form or
  113 + documentation, if provided along with the Derivative Works; or,
  114 + within a display generated by the Derivative Works, if and
  115 + wherever such third-party notices normally appear. The contents
  116 + of the NOTICE file are for informational purposes only and
  117 + do not modify the License. You may add Your own attribution
  118 + notices within Derivative Works that You distribute, alongside
  119 + or as an addendum to the NOTICE text from the Work, provided
  120 + that such additional attribution notices cannot be construed
  121 + as modifying the License.
  122 +
  123 + You may add Your own copyright statement to Your modifications and
  124 + may provide additional or different license terms and conditions
  125 + for use, reproduction, or distribution of Your modifications, or
  126 + for any such Derivative Works as a whole, provided Your use,
  127 + reproduction, and distribution of the Work otherwise complies with
  128 + the conditions stated in this License.
  129 +
  130 + 5. Submission of Contributions. Unless You explicitly state otherwise,
  131 + any Contribution intentionally submitted for inclusion in the Work
  132 + by You to the Licensor shall be under the terms and conditions of
  133 + this License, without any additional terms or conditions.
  134 + Notwithstanding the above, nothing herein shall supersede or modify
  135 + the terms of any separate license agreement you may have executed
  136 + with Licensor regarding such Contributions.
  137 +
  138 + 6. Trademarks. This License does not grant permission to use the trade
  139 + names, trademarks, service marks, or product names of the Licensor,
  140 + except as required for reasonable and customary use in describing the
  141 + origin of the Work and reproducing the content of the NOTICE file.
  142 +
  143 + 7. Disclaimer of Warranty. Unless required by applicable law or
  144 + agreed to in writing, Licensor provides the Work (and each
  145 + Contributor provides its Contributions) on an "AS IS" BASIS,
  146 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
  147 + implied, including, without limitation, any warranties or conditions
  148 + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
  149 + PARTICULAR PURPOSE. You are solely responsible for determining the
  150 + appropriateness of using or redistributing the Work and assume any
  151 + risks associated with Your exercise of permissions under this License.
  152 +
  153 + 8. Limitation of Liability. In no event and under no legal theory,
  154 + whether in tort (including negligence), contract, or otherwise,
  155 + unless required by applicable law (such as deliberate and grossly
  156 + negligent acts) or agreed to in writing, shall any Contributor be
  157 + liable to You for damages, including any direct, indirect, special,
  158 + incidental, or consequential damages of any character arising as a
  159 + result of this License or out of the use or inability to use the
  160 + Work (including but not limited to damages for loss of goodwill,
  161 + work stoppage, computer failure or malfunction, or any and all
  162 + other commercial damages or losses), even if such Contributor
  163 + has been advised of the possibility of such damages.
  164 +
  165 + 9. Accepting Warranty or Additional Liability. While redistributing
  166 + the Work or Derivative Works thereof, You may choose to offer,
  167 + and charge a fee for, acceptance of support, warranty, indemnity,
  168 + or other liability obligations and/or rights consistent with this
  169 + License. However, in accepting such obligations, You may act only
  170 + on Your own behalf and on Your sole responsibility, not on behalf
  171 + of any other Contributor, and only if You agree to indemnify,
  172 + defend, and hold each Contributor harmless for any liability
  173 + incurred by, or claims asserted against, such Contributor by reason
  174 + of your accepting any such warranty or additional liability.
  175 +
  176 + END OF TERMS AND CONDITIONS
  177 +
  178 + APPENDIX: How to apply the Apache License to your work.
  179 +
  180 + To apply the Apache License to your work, attach the following
  181 + boilerplate notice, with the fields enclosed by brackets "{}"
  182 + replaced with your own identifying information. (Don't include
  183 + the brackets!) The text should be enclosed in the appropriate
  184 + comment syntax for the file format. We also recommend that a
  185 + file or class name and description of purpose be included on the
  186 + same "printed page" as the copyright notice for easier
  187 + identification within third-party archives.
  188 +
  189 + Copyright {yyyy} {name of copyright owner}
  190 +
  191 + Licensed under the Apache License, Version 2.0 (the "License");
  192 + you may not use this file except in compliance with the License.
  193 + You may obtain a copy of the License at
  194 +
  195 + http://www.apache.org/licenses/LICENSE-2.0
  196 +
  197 + Unless required by applicable law or agreed to in writing, software
  198 + distributed under the License is distributed on an "AS IS" BASIS,
  199 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  200 + See the License for the specific language governing permissions and
  201 + limitations under the License.
... ...
pom.xml 0 → 100644
  1 +++ a/pom.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <modelVersion>4.0.0</modelVersion>
  6 +
  7 + <groupId>org.mengyun</groupId>
  8 + <artifactId>tcc-transaction</artifactId>
  9 + <packaging>pom</packaging>
  10 + <version>1.1.5_comment</version>
  11 + <modules>
  12 + <module>tcc-transaction-api</module>
  13 + <module>tcc-transaction-core</module>
  14 + <module>tcc-transaction-spring</module>
  15 + <!-- TODO:-->
  16 +
  17 + </modules>
  18 +
  19 + <properties>
  20 + <java.src.version>1.7</java.src.version>
  21 + <java.target.version>1.7</java.target.version>
  22 + <project.encoding>UTF-8</project.encoding>
  23 +
  24 + <my-nexus-releases-url>http://139.196.164.188:8081/nexus/content/repositories/releases/</my-nexus-releases-url>
  25 + <my-nexus-snapshots-url>http://139.196.164.188:8081/nexus/content/repositories/snapshots/</my-nexus-snapshots-url>
  26 +
  27 + <!-- 依赖的框架相关属性 -->
  28 + <log-slf4j.version>1.7.16</log-slf4j.version>
  29 + <log-logback.version>1.1.5</log-logback.version>
  30 + <quartz.version>2.3.0</quartz.version>
  31 +
  32 + <toolkit-google-guava.version>19.0</toolkit-google-guava.version>
  33 + <toolkit-javac-janino.version>2.7.8</toolkit-javac-janino.version>
  34 +
  35 + <fullstack-springframework.version>4.2.5.RELEASE</fullstack-springframework.version>
  36 +
  37 + <!-- TODO: -->
  38 +
  39 + </properties>
  40 +
  41 + <dependencyManagement>
  42 + <dependencies>
  43 + <dependency>
  44 + <groupId>org.mengyun</groupId>
  45 + <artifactId>tcc-transaction-api</artifactId>
  46 + <version>${project.version}</version>
  47 + </dependency>
  48 +
  49 + <dependency>
  50 + <groupId>org.mengyun</groupId>
  51 + <artifactId>tcc-transaction-core</artifactId>
  52 + <version>${project.version}</version>
  53 + </dependency>
  54 +
  55 + <!-- google相关 begin -->
  56 + <dependency>
  57 + <groupId>com.google.guava</groupId>
  58 + <artifactId>guava</artifactId>
  59 + <version>${toolkit-google-guava.version}</version>
  60 + </dependency>
  61 + <!-- google相关 end -->
  62 +
  63 + <!-- 日志处理相关 begin -->
  64 + <dependency>
  65 + <groupId>org.slf4j</groupId>
  66 + <artifactId>slf4j-api</artifactId>
  67 + <version>${log-slf4j.version}</version>
  68 + </dependency>
  69 + <dependency>
  70 + <groupId>org.slf4j</groupId>
  71 + <artifactId>jcl-over-slf4j</artifactId>
  72 + <version>${log-slf4j.version}</version>
  73 + </dependency>
  74 + <dependency>
  75 + <groupId>org.slf4j</groupId>
  76 + <artifactId>jul-to-slf4j</artifactId>
  77 + <version>${log-slf4j.version}</version>
  78 + </dependency>
  79 + <dependency>
  80 + <groupId>org.slf4j</groupId>
  81 + <artifactId>log4j-over-slf4j</artifactId>
  82 + <version>${log-slf4j.version}</version>
  83 + </dependency>
  84 + <dependency>
  85 + <groupId>ch.qos.logback</groupId>
  86 + <artifactId>logback-access</artifactId>
  87 + <version>${log-logback.version}</version>
  88 + </dependency>
  89 + <dependency>
  90 + <groupId>ch.qos.logback</groupId>
  91 + <artifactId>logback-classic</artifactId>
  92 + <version>${log-logback.version}</version>
  93 + </dependency>
  94 + <dependency>
  95 + <groupId>org.codehaus.janino</groupId>
  96 + <artifactId>commons-compiler</artifactId>
  97 + <version>${toolkit-javac-janino.version}</version>
  98 + </dependency>
  99 + <dependency>
  100 + <groupId>org.codehaus.janino</groupId>
  101 + <artifactId>janino</artifactId>
  102 + <version>${toolkit-javac-janino.version}</version>
  103 + </dependency>
  104 + <!-- 日志处理相关 end -->
  105 +
  106 + <!-- spring相关 begin -->
  107 + <dependency>
  108 + <groupId>org.springframework</groupId>
  109 + <artifactId>spring-aspects</artifactId>
  110 + <version>${fullstack-springframework.version}</version>
  111 + </dependency>
  112 + <dependency>
  113 + <groupId>org.springframework</groupId>
  114 + <artifactId>spring-aop</artifactId>
  115 + <version>${fullstack-springframework.version}</version>
  116 + </dependency>
  117 + <dependency>
  118 + <groupId>org.springframework</groupId>
  119 + <artifactId>spring-jdbc</artifactId>
  120 + <version>${fullstack-springframework.version}</version>
  121 + </dependency>
  122 + <dependency>
  123 + <groupId>org.springframework</groupId>
  124 + <artifactId>spring-context</artifactId>
  125 + <version>${fullstack-springframework.version}</version>
  126 + </dependency>
  127 + <dependency>
  128 + <groupId>org.springframework</groupId>
  129 + <artifactId>spring-context-support</artifactId>
  130 + <version>${fullstack-springframework.version}</version>
  131 + </dependency>
  132 + <!-- spring相关 end -->
  133 +
  134 + <!-- quartz相关 begin -->
  135 + <dependency>
  136 + <groupId>org.quartz-scheduler</groupId>
  137 + <artifactId>quartz</artifactId>
  138 + <version>${quartz.version}</version>
  139 + <exclusions>
  140 + <exclusion>
  141 + <artifactId>c3p0</artifactId>
  142 + <groupId>com.mchange</groupId>
  143 + </exclusion>
  144 + <exclusion>
  145 + <artifactId>HikariCP-java6</artifactId>
  146 + <groupId>com.zaxxer</groupId>
  147 + </exclusion>
  148 + </exclusions>
  149 + </dependency>
  150 + <!-- quartz相关 end -->
  151 +
  152 + <!-- TODO: -->
  153 +
  154 + </dependencies>
  155 + </dependencyManagement>
  156 +
  157 + <build>
  158 + <resources>
  159 + <resource>
  160 + <directory>src/main/resources</directory>
  161 + <filtering>true</filtering>
  162 + </resource>
  163 + </resources>
  164 + <testResources>
  165 + <testResource>
  166 + <directory>src/test/resources</directory>
  167 + <filtering>true</filtering>
  168 + </testResource>
  169 + </testResources>
  170 +
  171 + <plugins>
  172 + <plugin>
  173 + <groupId>org.apache.maven.plugins</groupId>
  174 + <artifactId>maven-resources-plugin</artifactId>
  175 + <version>2.4</version>
  176 + <configuration>
  177 + <encoding>${project.encoding}</encoding>
  178 + </configuration>
  179 + </plugin>
  180 + <plugin>
  181 + <groupId>org.apache.maven.plugins</groupId>
  182 + <artifactId>maven-compiler-plugin</artifactId>
  183 + <version>2.3.2</version>
  184 + <configuration>
  185 + <source>${java.src.version}</source>
  186 + <target>${java.target.version}</target>
  187 + <encoding>${project.encoding}</encoding>
  188 + </configuration>
  189 + </plugin>
  190 + <plugin>
  191 + <groupId>org.apache.maven.plugins</groupId>
  192 + <artifactId>maven-source-plugin</artifactId>
  193 + <version>2.2.1</version>
  194 + <executions>
  195 + <execution>
  196 + <id>attach-sources</id>
  197 + <goals>
  198 + <goal>jar</goal>
  199 + </goals>
  200 + </execution>
  201 + </executions>
  202 + </plugin>
  203 + <plugin>
  204 + <groupId>org.apache.maven.plugins</groupId>
  205 + <artifactId>maven-deploy-plugin</artifactId>
  206 + <version>2.7</version>
  207 + <configuration>
  208 + <updateReleaseInfo>true</updateReleaseInfo>
  209 + </configuration>
  210 + </plugin>
  211 + </plugins>
  212 +
  213 + </build>
  214 +
  215 + <distributionManagement>
  216 + <repository>
  217 + <id>my-nexus-releases</id>
  218 + <name>Nexus Release Repository</name>
  219 + <url>${my-nexus-releases-url}</url>
  220 + </repository>
  221 + <snapshotRepository>
  222 + <id>my-nexus-snapshots</id>
  223 + <name>Nexus Snapshot Repository</name>
  224 + <url>${my-nexus-snapshots-url}</url>
  225 + </snapshotRepository>
  226 + </distributionManagement>
  227 +
  228 +
  229 +</project>
0 230 \ No newline at end of file
... ...
tcc-transaction-api/pom.xml 0 → 100644
  1 +++ a/tcc-transaction-api/pom.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>tcc-transaction</artifactId>
  7 + <groupId>org.mengyun</groupId>
  8 + <version>1.1.5_comment</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>tcc-transaction-api</artifactId>
  13 +
  14 +</project>
0 15 \ No newline at end of file
... ...
tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/TransactionContext.java 0 → 100644
  1 +++ a/tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/TransactionContext.java
  1 +package org.mengyun.tcctransaction.api;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.Map;
  5 +import java.util.concurrent.ConcurrentHashMap;
  6 +
  7 +/**
  8 + * Created by changmingxie on 10/30/15.
  9 + * 事务上下文.
  10 + */
  11 +public class TransactionContext implements Serializable {
  12 + private static final long serialVersionUID = -8199390103169700387L;
  13 +
  14 + /** 事务Id */
  15 + private TransactionXid xid;
  16 + /** 事务状态(参见:TransactionStatus) */
  17 + private int status;
  18 +
  19 + /**
  20 + * 附加属性.
  21 + */
  22 + private Map<String, String> attachments = new ConcurrentHashMap<>();
  23 +
  24 + public TransactionContext() {
  25 +
  26 + }
  27 +
  28 + /**
  29 + * 构建事务上下文对像.
  30 + * @param xid
  31 + * @param status
  32 + */
  33 + public TransactionContext(TransactionXid xid, int status) {
  34 + this.xid = xid;
  35 + this.status = status;
  36 + }
  37 +
  38 + public void setXid(TransactionXid xid) {
  39 + this.xid = xid;
  40 + }
  41 +
  42 + public TransactionXid getXid() {
  43 + return xid.clone();
  44 + }
  45 +
  46 + public void setAttachments(Map<String, String> attachments) {
  47 + this.attachments = attachments;
  48 + }
  49 +
  50 + public Map<String, String> getAttachments() {
  51 + return attachments;
  52 + }
  53 +
  54 + public void setStatus(int status) {
  55 + this.status = status;
  56 + }
  57 +
  58 + public int getStatus() {
  59 + return status;
  60 + }
  61 +}
... ...
tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/TransactionStatus.java 0 → 100644
  1 +++ a/tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/TransactionStatus.java
  1 +package org.mengyun.tcctransaction.api;
  2 +
  3 +/**
  4 + * Created by changmingxie on 10/28/15.
  5 + * 事务状态枚举.
  6 + */
  7 +public enum TransactionStatus {
  8 + /**
  9 + * 尝试中:1
  10 + */
  11 + TRYING(1),
  12 + /**
  13 + * 确认中:2
  14 + */
  15 + CONFIRMING(2),
  16 + /**
  17 + * 取消中:3
  18 + */
  19 + CANCELLING(3);
  20 +
  21 + private int id;
  22 + public int getId() {
  23 + return id;
  24 + }
  25 +
  26 + TransactionStatus(int id) {
  27 + this.id = id;
  28 + }
  29 +
  30 + public static TransactionStatus valueOf(int id) {
  31 + switch (id) {
  32 + case 1:
  33 + return TRYING;
  34 + case 2:
  35 + return CONFIRMING;
  36 + default:
  37 + return CANCELLING;
  38 + }
  39 + }
  40 +}
... ...
tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/TransactionXid.java 0 → 100644
  1 +++ a/tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/TransactionXid.java
  1 +package org.mengyun.tcctransaction.api;
  2 +
  3 +import javax.transaction.xa.Xid;
  4 +import java.io.Serializable;
  5 +import java.util.Arrays;
  6 +import java.util.UUID;
  7 +
  8 +/**
  9 + * Created by changmingxie on 10/26/15.
  10 + *
  11 + * 添加注释:
  12 + * Xid接口是X/Open事务标识符XID结构的Java映射。
  13 + * 1、globalTransactionId 表示主事务Id
  14 + * 2、branchQualifier 表示分支事务Id
  15 + * 3、formatId用于标识globalTransactionId和branchQualifier格式
  16 + *
  17 + * 说明:
  18 + * 1、一般分布式事务由一个主事务和多个分支事务组成
  19 + * 2、相同主事务的分支事务的globalTransactionId相同
  20 + * 3、相同主事务的分支事务的branchQualifier必须唯一
  21 + * 4、globalTransactionId和branchQualifier为字节数组,并不明确是什么类型(字符串或者数字),使用formatId标识
  22 + *
  23 + * 参考 MySql中分布式事务的使用:
  24 + * http://www.jeepxie.net/article/238022.html
  25 + * http://www.tianshouzhi.com/api/tutorials/distributed_transaction/384
  26 + *
  27 + */
  28 +public class TransactionXid implements Xid, Serializable {
  29 + private static final long serialVersionUID = -6817267250789142043L;
  30 +
  31 + /** XID的格式标识符(默认值为1) */
  32 + private int formatId = 1;
  33 +
  34 + /** 全局事务ID */
  35 + private byte[] globalTransactionId;
  36 +
  37 + /** 分支限定符 */
  38 + private byte[] branchQualifier;
  39 +
  40 + public TransactionXid() {
  41 + globalTransactionId = UuidUtils.uuidToByteArray(UUID.randomUUID());
  42 + branchQualifier = UuidUtils.uuidToByteArray(UUID.randomUUID());
  43 + }
  44 +
  45 + public TransactionXid(byte[] globalTransactionId) {
  46 + this.globalTransactionId = globalTransactionId;
  47 + branchQualifier = UuidUtils.uuidToByteArray(UUID.randomUUID());
  48 + }
  49 +
  50 + public TransactionXid(byte[] globalTransactionId, byte[] branchQualifier) {
  51 + this.globalTransactionId = globalTransactionId;
  52 + this.branchQualifier = branchQualifier;
  53 + }
  54 +
  55 + /**
  56 + * 获取 XID 的格式标识符部分。
  57 + */
  58 + @Override
  59 + public int getFormatId() {
  60 + return formatId;
  61 + }
  62 +
  63 + /**
  64 + * 获取 XID 的全局事务标识符部分作为字节数组。
  65 + */
  66 + @Override
  67 + public byte[] getGlobalTransactionId() {
  68 + return globalTransactionId;
  69 + }
  70 +
  71 + /**
  72 + * 获取 XID 的事务分支标识符部分作为字节数组。
  73 + */
  74 + @Override
  75 + public byte[] getBranchQualifier() {
  76 + return branchQualifier;
  77 + }
  78 +
  79 + @Override
  80 + public String toString() {
  81 + return UUID.nameUUIDFromBytes(
  82 + globalTransactionId).toString() +
  83 + "|" +
  84 + UUID.nameUUIDFromBytes(branchQualifier).toString();
  85 + }
  86 +
  87 + /**
  88 + * 克隆事务Id.
  89 + */
  90 + @Override
  91 + public TransactionXid clone() {
  92 + byte[] cloneGlobalTransactionId = new byte[globalTransactionId.length];
  93 + byte[] cloneBranchQualifier = new byte[branchQualifier.length];
  94 +
  95 + System.arraycopy(globalTransactionId, 0, cloneGlobalTransactionId, 0, globalTransactionId.length);
  96 + System.arraycopy(branchQualifier, 0, cloneBranchQualifier, 0, branchQualifier.length);
  97 +
  98 + TransactionXid clone = new TransactionXid(cloneGlobalTransactionId, cloneBranchQualifier);
  99 + return clone;
  100 + }
  101 +
  102 + @Override
  103 + public int hashCode() {
  104 + final int prime = 31;
  105 + int result = 1;
  106 + result = prime * result + this.getFormatId();
  107 + result = prime * result + Arrays.hashCode(branchQualifier);
  108 + result = prime * result + Arrays.hashCode(globalTransactionId);
  109 + return result;
  110 + }
  111 +
  112 + public boolean equals(Object obj) {
  113 + if (this == obj) {
  114 + return true;
  115 + } else if (obj == null) {
  116 + return false;
  117 + } else if (getClass() != obj.getClass()) {
  118 + return false;
  119 + }
  120 + TransactionXid other = (TransactionXid) obj;
  121 + if (this.getFormatId() != other.getFormatId()) {
  122 + return false;
  123 + } else if (!Arrays.equals(branchQualifier, other.branchQualifier)) {
  124 + return false;
  125 + } else if (!Arrays.equals(globalTransactionId, other.globalTransactionId)) {
  126 + return false;
  127 + }
  128 + return true;
  129 + }
  130 +
  131 + /**
  132 + * 测试构造Xid。
  133 + */
  134 + public static void main(String[] args) {
  135 + byte[] gt = UUID.randomUUID().toString().getBytes();
  136 + byte[] bt = UUID.randomUUID().toString().getBytes();
  137 +
  138 + TransactionXid transactionXid = new TransactionXid(gt, bt);
  139 +
  140 + System.out.println(transactionXid);
  141 + }
  142 +
  143 +}
... ...
tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/UuidUtils.java 0 → 100644
  1 +++ a/tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/UuidUtils.java
  1 +package org.mengyun.tcctransaction.api;
  2 +
  3 +import java.nio.ByteBuffer;
  4 +import java.util.UUID;
  5 +
  6 +/**
  7 + * Created by changming.xie on 5/31/16.
  8 + */
  9 +public class UuidUtils {
  10 + public static byte[] uuidToByteArray(UUID uuid) {
  11 + ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
  12 + bb.putLong(uuid.getMostSignificantBits());
  13 + bb.putLong(uuid.getLeastSignificantBits());
  14 + return bb.array();
  15 + }
  16 +
  17 + public static UUID byteArrayToUUID(byte[] bytes) {
  18 + ByteBuffer bb = ByteBuffer.wrap(bytes);
  19 + long firstLong = bb.getLong();
  20 + long secondLong = bb.getLong();
  21 + return new UUID(firstLong, secondLong);
  22 + }
  23 +}
... ...
tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/annotation/Compensable.java 0 → 100644
  1 +++ a/tcc-transaction-api/src/main/java/org/mengyun/tcctransaction/api/annotation/Compensable.java
  1 +package org.mengyun.tcctransaction.api.annotation;
  2 +
  3 +import java.lang.annotation.ElementType;
  4 +import java.lang.annotation.Retention;
  5 +import java.lang.annotation.RetentionPolicy;
  6 +import java.lang.annotation.Target;
  7 +
  8 +/**
  9 + * Created by changmingxie on 10/25/15.
  10 + * 事务补偿注解。
  11 + */
  12 +@Retention(RetentionPolicy.RUNTIME)
  13 +@Target({ ElementType.METHOD })
  14 +public @interface Compensable {
  15 +
  16 + public String confirmMethod() default "";
  17 +
  18 + public String cancelMethod() default "";
  19 +}
... ...
tcc-transaction-api/target/classes/org/mengyun/tcctransaction/api/TransactionContext.class 0 → 100644
No preview for this file type
tcc-transaction-api/target/classes/org/mengyun/tcctransaction/api/TransactionStatus.class 0 → 100644
No preview for this file type
tcc-transaction-api/target/classes/org/mengyun/tcctransaction/api/TransactionXid.class 0 → 100644
No preview for this file type
tcc-transaction-api/target/classes/org/mengyun/tcctransaction/api/UuidUtils.class 0 → 100644
No preview for this file type
tcc-transaction-api/target/classes/org/mengyun/tcctransaction/api/annotation/Compensable.class 0 → 100644
No preview for this file type
tcc-transaction-api/target/maven-archiver/pom.properties 0 → 100644
  1 +++ a/tcc-transaction-api/target/maven-archiver/pom.properties
  1 +#Generated by Maven
  2 +#Thu Jan 02 11:02:11 CST 2020
  3 +version=1.1.5_comment
  4 +groupId=org.mengyun
  5 +artifactId=tcc-transaction-api
... ...
tcc-transaction-api/target/tcc-transaction-api-1.1.5_comment-sources.jar 0 → 100644
No preview for this file type
tcc-transaction-api/target/tcc-transaction-api-1.1.5_comment.jar 0 → 100644
No preview for this file type
tcc-transaction-core/pom.xml 0 → 100644
  1 +++ a/tcc-transaction-core/pom.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>tcc-transaction</artifactId>
  7 + <groupId>org.mengyun</groupId>
  8 + <version>1.1.5_comment</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>tcc-transaction-core</artifactId>
  13 +
  14 + <dependencies>
  15 + <dependency>
  16 + <groupId>org.mengyun</groupId>
  17 + <artifactId>tcc-transaction-api</artifactId>
  18 + </dependency>
  19 +
  20 + <!-- google相关 begin -->
  21 + <dependency>
  22 + <groupId>com.google.guava</groupId>
  23 + <artifactId>guava</artifactId>
  24 + </dependency>
  25 + <!-- google相关 end -->
  26 +
  27 + <!-- 日志处理相关 begin -->
  28 + <dependency>
  29 + <groupId>org.slf4j</groupId>
  30 + <artifactId>slf4j-api</artifactId>
  31 + </dependency>
  32 + <dependency>
  33 + <groupId>org.slf4j</groupId>
  34 + <artifactId>jcl-over-slf4j</artifactId>
  35 + </dependency>
  36 + <dependency>
  37 + <groupId>org.slf4j</groupId>
  38 + <artifactId>jul-to-slf4j</artifactId>
  39 + </dependency>
  40 + <dependency>
  41 + <groupId>org.slf4j</groupId>
  42 + <artifactId>log4j-over-slf4j</artifactId>
  43 + </dependency>
  44 + <dependency>
  45 + <groupId>ch.qos.logback</groupId>
  46 + <artifactId>logback-access</artifactId>
  47 + </dependency>
  48 + <dependency>
  49 + <groupId>ch.qos.logback</groupId>
  50 + <artifactId>logback-classic</artifactId>
  51 + </dependency>
  52 + <dependency>
  53 + <groupId>org.codehaus.janino</groupId>
  54 + <artifactId>commons-compiler</artifactId>
  55 + </dependency>
  56 + <dependency>
  57 + <groupId>org.codehaus.janino</groupId>
  58 + <artifactId>janino</artifactId>
  59 + </dependency>
  60 + <!-- 日志处理相关 end -->
  61 +
  62 + <!-- spring相关 begin -->
  63 + <dependency>
  64 + <groupId>org.springframework</groupId>
  65 + <artifactId>spring-aspects</artifactId>
  66 + </dependency>
  67 + <!-- spring相关 end -->
  68 +
  69 +
  70 + </dependencies>
  71 +
  72 +</project>
0 73 \ No newline at end of file
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/Transaction.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/Transaction.java
  1 +package org.mengyun.tcctransaction;
  2 +
  3 +import org.mengyun.tcctransaction.api.TransactionContext;
  4 +import org.mengyun.tcctransaction.api.TransactionStatus;
  5 +import org.mengyun.tcctransaction.api.TransactionXid;
  6 +import org.mengyun.tcctransaction.interceptor.Participant;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +
  10 +import javax.transaction.xa.Xid;
  11 +import java.io.Serializable;
  12 +import java.util.*;
  13 +import java.util.concurrent.ConcurrentHashMap;
  14 +
  15 +/**
  16 + * Created by changmingxie on 10/26/15.
  17 + * 事务类。
  18 + */
  19 +public class Transaction implements Serializable {
  20 + private static final long serialVersionUID = 7291423944314337931L;
  21 +
  22 + /** 日志记录器 */
  23 + private final static Logger LOG = LoggerFactory.getLogger(Transaction.class);
  24 +
  25 + /** 事务XID */
  26 + private TransactionXid xid;
  27 + public Xid getXid() {
  28 + return xid.clone();
  29 + }
  30 +
  31 + /** 事务状态 */
  32 + private TransactionStatus status;
  33 + public TransactionStatus getStatus() {
  34 + return status;
  35 + }
  36 + public void changeStatus(TransactionStatus status) {
  37 + this.status = status;
  38 + }
  39 +
  40 + /** 事务类型 */
  41 + private TransactionType transactionType;
  42 + public TransactionType getTransactionType() {
  43 + return transactionType;
  44 + }
  45 +
  46 + /** 事务恢复重试次数 */
  47 + private volatile int retriedCount = 0;
  48 + public int getRetriedCount() {
  49 + return retriedCount;
  50 + }
  51 + public void addRetriedCount() {
  52 + this.retriedCount ++;
  53 + }
  54 + public void resetRetriedCount(int retriedCount) {
  55 + this.retriedCount = retriedCount;
  56 + }
  57 +
  58 + /** 创建时间 */
  59 + private Date createTime = new Date();
  60 + public Date getCreateTime() {
  61 + return createTime;
  62 + }
  63 +
  64 + /** 最后更新时间 */
  65 + private Date lastUpdateTime = new Date();
  66 + public Date getLastUpdateTime() {
  67 + return lastUpdateTime;
  68 + }
  69 + public void setLastUpdateTime(Date date) {
  70 + this.lastUpdateTime = date;
  71 + }
  72 + public void updateTime() {
  73 + this.lastUpdateTime = new Date();
  74 + }
  75 +
  76 + /** 版本(默认值为1) */
  77 + private long version = 1;
  78 + public void updateVersion() {
  79 + this.version++;
  80 + }
  81 + public long getVersion() {
  82 + return version;
  83 + }
  84 + public void setVersion(long version) {
  85 + this.version = version;
  86 + }
  87 +
  88 + /** 附加属性 */
  89 + private Map<String, Object> attachments = new ConcurrentHashMap<String, Object>();
  90 +
  91 + /** 参与者列表 */
  92 + private List<Participant> participants = new ArrayList<Participant>();
  93 + public List<Participant> getParticipants() {
  94 + return Collections.unmodifiableList(participants);
  95 + }
  96 + /**
  97 + * 招募参与者(加入参与者)
  98 + * @param participant
  99 + */
  100 + public void enlistParticipant(Participant participant) {
  101 + participants.add(participant);
  102 + }
  103 +
  104 + /**
  105 + * 事务构造方法(基于全局事务id创建新的分支事务)
  106 + * 通过transactionContext传入Xid,默认状态为TRYING:1,默认事务类型为BRANCH:2
  107 + * @param transactionContext
  108 + */
  109 + public Transaction(TransactionContext transactionContext) {
  110 + this.xid = transactionContext.getXid();
  111 + this.status = TransactionStatus.TRYING;
  112 + this.transactionType = TransactionType.BRANCH;
  113 + }
  114 +
  115 + /**
  116 + * 事务构造方法,传入transactionType,默认状态为TRYING:1,Xid自动生成
  117 + * @param transactionType
  118 + */
  119 + public Transaction(TransactionType transactionType) {
  120 + this.xid = new TransactionXid();
  121 + this.status = TransactionStatus.TRYING;
  122 + this.transactionType = transactionType;
  123 + }
  124 +
  125 + /**
  126 + * 事务提交(包含此事务的所有参与者的逐个提交,在TransactionManager中被调用).
  127 + */
  128 + public void commit() {
  129 + LOG.debug("==>Transaction commit()");
  130 + for (Participant participant : participants) {
  131 + participant.commit();
  132 + }
  133 + }
  134 +
  135 + /**
  136 + * 事务回滚(包含此事务的所有参与者的逐个回滚,在TransactionManager中被调用).
  137 + */
  138 + public void rollback() {
  139 + LOG.debug("==>Transaction rollback()");
  140 + for (Participant participant : participants) {
  141 + participant.rollback();
  142 + }
  143 + }
  144 +
  145 +
  146 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/TransactionManager.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/TransactionManager.java
  1 +package org.mengyun.tcctransaction;
  2 +
  3 +import org.mengyun.tcctransaction.api.TransactionContext;
  4 +import org.mengyun.tcctransaction.api.TransactionStatus;
  5 +import org.mengyun.tcctransaction.api.UuidUtils;
  6 +import org.mengyun.tcctransaction.exception.CancellingException;
  7 +import org.mengyun.tcctransaction.exception.ConfirmingException;
  8 +import org.mengyun.tcctransaction.exception.NoExistedTransactionException;
  9 +import org.mengyun.tcctransaction.repository.TransactionRepository;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +
  13 +/**
  14 + * Created by changmingxie on 10/26/15.
  15 + * 事务管理器:开始事务,提交事务,回滚事务。
  16 + * 注意:此版本只支持单一线程一个主事务,不支持嵌套主事务,后续版本会支持。
  17 + *
  18 + */
  19 +public class TransactionManager {
  20 + /** 日志记录器 */
  21 + private static final Logger LOG = LoggerFactory.getLogger(TransactionManager.class);
  22 +
  23 + /** 事务库repo */
  24 + private TransactionRepository transactionRepository;
  25 + public void setTransactionRepository(TransactionRepository transactionRepository) {
  26 + this.transactionRepository = transactionRepository;
  27 + }
  28 +
  29 + /** 事务线程局部变量 */
  30 + private ThreadLocal<Transaction> threadLocalTransaction = new ThreadLocal<Transaction>();
  31 + public Transaction getCurrentTransaction() {
  32 + return threadLocalTransaction.get();
  33 + }
  34 +
  35 +
  36 + /**
  37 + * 事务开始(创建事务日志记录,并将该事务日志记录存入当前线程的事务局部变量中)
  38 + */
  39 + public void begin() {
  40 + LOG.debug("==>TransactionManager begin()");
  41 + Transaction transaction = new Transaction(TransactionType.ROOT); // 事务类型为ROOT:1
  42 + LOG.debug("==>TransactionManager TransactionType:" + transaction.getTransactionType().toString() + ", Transaction Status:" + transaction.getStatus().toString());
  43 + transactionRepository.create(transaction); // 创建事务记录,写入事务日志库
  44 + threadLocalTransaction.set(transaction); // 将该事务日志记录存入当前线程的事务局部变量中
  45 + }
  46 +
  47 + /**
  48 + * 提交事务.
  49 + */
  50 + public void commit() {
  51 + LOG.debug("==>TransactionManager commit()");
  52 + Transaction transaction = getCurrentTransaction();
  53 +
  54 + transaction.changeStatus(TransactionStatus.CONFIRMING);
  55 + LOG.debug("==>TransactionManager update transaction status to CONFIRMING");
  56 + transactionRepository.update(transaction);
  57 +
  58 + try {
  59 + LOG.info("==>TransactionManager transaction begin commit()");
  60 + transaction.commit();
  61 + transactionRepository.delete(transaction);
  62 + } catch (Throwable commitException) {
  63 + LOG.error("TransactionManager compensable transaction confirm failed.", commitException);
  64 + throw new ConfirmingException(commitException);
  65 + }
  66 + }
  67 +
  68 + /**
  69 + * 回滚事务.
  70 + */
  71 + public void rollback() {
  72 + LOG.debug("==>TransactionManager rollback()");
  73 +
  74 + Transaction transaction = getCurrentTransaction();
  75 + transaction.changeStatus(TransactionStatus.CANCELLING);
  76 + transactionRepository.update(transaction);
  77 +
  78 + try {
  79 + LOG.info("==>TransactionManager transaction begin rollback()");
  80 + transaction.rollback();
  81 + transactionRepository.delete(transaction);
  82 + } catch (Throwable rollbackException) {
  83 + LOG.error("TransactionManager compensable transaction rollback failed.", rollbackException);
  84 + throw new CancellingException(rollbackException);
  85 + }
  86 + }
  87 +
  88 + /**
  89 + * 基于全局事务ID扩展创建新的分支事务,并存于当前线程的事务局部变量中.
  90 + * @param transactionContext
  91 + */
  92 + public void propagationNewBegin(TransactionContext transactionContext) {
  93 +
  94 + Transaction transaction = new Transaction(transactionContext);
  95 + LOG.debug("==>TransactionManager propagationNewBegin TransactionXid:" + UuidUtils.byteArrayToUUID(transaction.getXid().getGlobalTransactionId()).toString()
  96 + + "|" + UuidUtils.byteArrayToUUID(transaction.getXid().getBranchQualifier()).toString());
  97 +
  98 + transactionRepository.create(transaction);
  99 + threadLocalTransaction.set(transaction);
  100 + }
  101 +
  102 + /**
  103 + * 找出存在的事务并处理.
  104 + * @param transactionContext
  105 + * @throws NoExistedTransactionException
  106 + */
  107 + public void propagationExistBegin(TransactionContext transactionContext) throws NoExistedTransactionException {
  108 + Transaction transaction = transactionRepository.findByXid(transactionContext.getXid());
  109 +
  110 + if (transaction != null) {
  111 + LOG.debug("==>TransactionManager propagationExistBegin TransactionXid:" + UuidUtils.byteArrayToUUID(transaction.getXid().getGlobalTransactionId()).toString()
  112 + + "|" + UuidUtils.byteArrayToUUID(transaction.getXid().getBranchQualifier()).toString());
  113 +
  114 + transaction.changeStatus(TransactionStatus.valueOf(transactionContext.getStatus()));
  115 + threadLocalTransaction.set(transaction);
  116 + } else {
  117 + throw new NoExistedTransactionException();
  118 + }
  119 + }
  120 +
  121 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/TransactionType.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/TransactionType.java
  1 +package org.mengyun.tcctransaction;
  2 +
  3 +/**
  4 + * Created by changmingxie on 11/15/15.
  5 + * 事务类型。
  6 + */
  7 +public enum TransactionType {
  8 + /**
  9 + * 主事务:1.
  10 + */
  11 + ROOT(1),
  12 +
  13 + /**
  14 + * 分支事务:2.
  15 + */
  16 + BRANCH(2);
  17 +
  18 + int id;
  19 +
  20 + TransactionType(int id) {
  21 + this.id = id;
  22 + }
  23 +
  24 + public int getId() {
  25 + return id;
  26 + }
  27 +
  28 + public static TransactionType valueOf(int id) {
  29 + switch (id) {
  30 + case 1:
  31 + return ROOT;
  32 + case 2:
  33 + return BRANCH;
  34 + default:
  35 + return null;
  36 + }
  37 + }
  38 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/CancellingException.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/CancellingException.java
  1 +package org.mengyun.tcctransaction.exception;
  2 +
  3 +/**
  4 + * Created by changming.xie on 7/21/16.
  5 + * 取消事务异常。
  6 + */
  7 +public class CancellingException extends RuntimeException {
  8 + public CancellingException(Throwable cause) {
  9 + super(cause);
  10 + }
  11 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/ConfirmingException.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/ConfirmingException.java
  1 +package org.mengyun.tcctransaction.exception;
  2 +
  3 +/**
  4 + * Created by changming.xie on 7/21/16.
  5 + * 确认事务异常。
  6 + */
  7 +public class ConfirmingException extends RuntimeException {
  8 + public ConfirmingException(Throwable cause) {
  9 + super(cause);
  10 + }
  11 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/NoExistedTransactionException.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/NoExistedTransactionException.java
  1 +package org.mengyun.tcctransaction.exception;
  2 +
  3 +/**
  4 + * Created by changmingxie on 12/16/15.
  5 + * 事务不存在异常。
  6 + */
  7 +public class NoExistedTransactionException extends Exception {
  8 + private static final long serialVersionUID = 1031919168789207713L;
  9 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/OptimisticLockException.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/OptimisticLockException.java
  1 +package org.mengyun.tcctransaction.exception;
  2 +
  3 +/**
  4 + * Created by changming.xie on 7/21/16.
  5 + * 乐观锁异常。
  6 + */
  7 +public class OptimisticLockException extends RuntimeException {
  8 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/SystemException.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/SystemException.java
  1 +package org.mengyun.tcctransaction.exception;
  2 +
  3 +/**
  4 + * Created by changming.xie on 6/1/16.
  5 + * 系统异常。
  6 + */
  7 +public class SystemException extends RuntimeException {
  8 + public SystemException(String message) {
  9 + super(message);
  10 + }
  11 +
  12 + public SystemException(Throwable e) {
  13 + super(e);
  14 + }
  15 +
  16 + public SystemException(String message, Throwable e) {
  17 + super(message, e);
  18 + }
  19 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/TransactionIOException.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/exception/TransactionIOException.java
  1 +package org.mengyun.tcctransaction.exception;
  2 +
  3 +/**
  4 + * Created by hongyuan.wang on 2016/1/26.
  5 + * 事务IO异常。
  6 + */
  7 +public class TransactionIOException extends RuntimeException {
  8 + private static final long serialVersionUID = 6508064607297986329L;
  9 +
  10 + public TransactionIOException(String message) {
  11 + super(message);
  12 + }
  13 +
  14 + public TransactionIOException(Throwable e) {
  15 + super(e);
  16 + }
  17 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/CompensableTransactionInterceptor.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/CompensableTransactionInterceptor.java
  1 +package org.mengyun.tcctransaction.interceptor;
  2 +
  3 +import org.aspectj.lang.ProceedingJoinPoint;
  4 +import org.aspectj.lang.reflect.MethodSignature;
  5 +import org.mengyun.tcctransaction.api.TransactionContext;
  6 +import org.mengyun.tcctransaction.api.TransactionStatus;
  7 +import org.mengyun.tcctransaction.exception.NoExistedTransactionException;
  8 +import org.mengyun.tcctransaction.exception.OptimisticLockException;
  9 +import org.mengyun.tcctransaction.interceptor.utils.CompensableMethodUtils;
  10 +import org.mengyun.tcctransaction.interceptor.utils.MethodType;
  11 +import org.mengyun.tcctransaction.interceptor.utils.ReflectionUtils;
  12 +import org.mengyun.tcctransaction.support.TransactionConfigurator;
  13 +import org.slf4j.Logger;
  14 +import org.slf4j.LoggerFactory;
  15 +
  16 +import java.lang.reflect.Method;
  17 +
  18 +/**
  19 + * Created by changmingxie on 10/30/15.
  20 + * 可补偿事务拦截器。
  21 + */
  22 +public class CompensableTransactionInterceptor {
  23 + /** 日志记录器 */
  24 + private static final Logger LOG = LoggerFactory.getLogger(CompensableTransactionInterceptor.class);
  25 +
  26 + /** 事务配置器 */
  27 + private TransactionConfigurator transactionConfigurator;
  28 + public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
  29 + this.transactionConfigurator = transactionConfigurator;
  30 + }
  31 +
  32 + /**
  33 + * 拦截补偿方法.
  34 + * @param pjp
  35 + * @throws Throwable
  36 + */
  37 + public Object interceptCompensableMethod(ProceedingJoinPoint pjp) throws Throwable {
  38 +
  39 + // 从拦截方法的参数中获取事务上下文
  40 + TransactionContext transactionContext = CompensableMethodUtils.getTransactionContextFromArgs(pjp.getArgs());
  41 +
  42 + // 计算可补偿事务方法类型
  43 + MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, true);
  44 +
  45 + LOG.debug("==>interceptCompensableMethod methodType:" + methodType.toString());
  46 +
  47 + switch (methodType) {
  48 + case ROOT:
  49 + return rootMethodProceed(pjp); // 主事务方法的处理
  50 + case PROVIDER:
  51 + return providerMethodProceed(pjp, transactionContext); // 服务提供者事务方法处理
  52 + default:
  53 + return pjp.proceed(); // 其他的方法都是直接执行
  54 + }
  55 + }
  56 +
  57 + /**
  58 + * 主事务方法的处理.
  59 + * @param pjp
  60 + * @throws Throwable
  61 + */
  62 + private Object rootMethodProceed(ProceedingJoinPoint pjp) throws Throwable {
  63 + LOG.debug("==>rootMethodProceed");
  64 +
  65 + transactionConfigurator.getTransactionManager().begin(); // 事务开始(创建事务日志记录,并在当前线程缓存该事务日志记录)
  66 +
  67 + Object returnValue = null; // 返回值
  68 + try {
  69 +
  70 + LOG.debug("==>rootMethodProceed try begin");
  71 + returnValue = pjp.proceed(); // Try (开始执行被拦截的方法)
  72 + LOG.debug("==>rootMethodProceed try end");
  73 +
  74 + } catch (OptimisticLockException e) {
  75 + LOG.warn("==>compensable transaction trying exception.", e);
  76 + throw e; //do not rollback, waiting for recovery job
  77 + } catch (Throwable tryingException) {
  78 + LOG.warn("compensable transaction trying failed.", tryingException);
  79 + transactionConfigurator.getTransactionManager().rollback();
  80 + throw tryingException;
  81 + }
  82 +
  83 + LOG.info("===>rootMethodProceed begin commit()");
  84 + transactionConfigurator.getTransactionManager().commit(); // Try检验正常后提交(事务管理器在控制提交)
  85 +
  86 + return returnValue;
  87 + }
  88 +
  89 + /**
  90 + * 服务提供者事务方法处理.
  91 + * @param pjp
  92 + * @param transactionContext
  93 + * @throws Throwable
  94 + */
  95 + private Object providerMethodProceed(ProceedingJoinPoint pjp, TransactionContext transactionContext) throws Throwable {
  96 +
  97 + LOG.debug("==>providerMethodProceed transactionStatus:" + TransactionStatus.valueOf(transactionContext.getStatus()).toString());
  98 +
  99 + switch (TransactionStatus.valueOf(transactionContext.getStatus())) {
  100 + case TRYING:
  101 + LOG.debug("==>providerMethodProceed try begin");
  102 + // 基于全局事务ID扩展创建新的分支事务,并存于当前线程的事务局部变量中.
  103 + transactionConfigurator.getTransactionManager().propagationNewBegin(transactionContext);
  104 + LOG.debug("==>providerMethodProceed try end");
  105 + return pjp.proceed();
  106 + case CONFIRMING:
  107 + try {
  108 + LOG.debug("==>providerMethodProceed confirm begin");
  109 + // 找出存在的事务并处理.
  110 + transactionConfigurator.getTransactionManager().propagationExistBegin(transactionContext);
  111 + transactionConfigurator.getTransactionManager().commit(); // 提交
  112 + LOG.debug("==>providerMethodProceed confirm end");
  113 + } catch (NoExistedTransactionException excepton) {
  114 + //the transaction has been commit,ignore it.
  115 + }
  116 + break;
  117 + case CANCELLING:
  118 + try {
  119 + LOG.debug("==>providerMethodProceed cancel begin");
  120 + transactionConfigurator.getTransactionManager().propagationExistBegin(transactionContext);
  121 + transactionConfigurator.getTransactionManager().rollback(); // 回滚
  122 + LOG.debug("==>providerMethodProceed cancel end");
  123 + } catch (NoExistedTransactionException exception) {
  124 + //the transaction has been rollback,ignore it.
  125 + }
  126 + break;
  127 + }
  128 +
  129 + Method method = ((MethodSignature) (pjp.getSignature())).getMethod();
  130 +
  131 + return ReflectionUtils.getNullValue(method.getReturnType());
  132 + }
  133 +
  134 +
  135 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/Participant.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/Participant.java
  1 +package org.mengyun.tcctransaction.interceptor;
  2 +
  3 +import org.mengyun.tcctransaction.api.TransactionXid;
  4 +import org.mengyun.tcctransaction.interceptor.invoke.Terminator;
  5 +import org.slf4j.Logger;
  6 +import org.slf4j.LoggerFactory;
  7 +
  8 +import java.io.Serializable;
  9 +
  10 +/**
  11 + * Created by changmingxie on 10/27/15.
  12 + * 事务参与者。
  13 + */
  14 +public class Participant implements Serializable {
  15 + private static final long serialVersionUID = 4127729421281425247L;
  16 +
  17 + /** 日志记录器 */
  18 + private static final Logger LOG = LoggerFactory.getLogger(Participant.class);
  19 +
  20 + private TransactionXid xid;
  21 +
  22 + private Terminator terminator;
  23 +
  24 + public Participant() {
  25 +
  26 + }
  27 +
  28 + public Participant(TransactionXid xid, Terminator terminator) {
  29 + this.xid = xid;
  30 + this.terminator = terminator;
  31 + }
  32 +
  33 + /**
  34 + * 回滚参与者事务(在Transaction中被调用)
  35 + */
  36 + public void rollback() {
  37 + LOG.debug("==>Participant rollback()");
  38 + terminator.rollback();
  39 + }
  40 +
  41 + /**
  42 + * 提交参与者事务(在Transaction中被调用).
  43 + */
  44 + public void commit() {
  45 + LOG.debug("==>Participant commit()");
  46 + terminator.commit();
  47 + }
  48 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/ResourceCoordinatorInterceptor.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/ResourceCoordinatorInterceptor.java
  1 +package org.mengyun.tcctransaction.interceptor;
  2 +
  3 +import org.aspectj.lang.ProceedingJoinPoint;
  4 +import org.aspectj.lang.reflect.MethodSignature;
  5 +import org.mengyun.tcctransaction.Transaction;
  6 +import org.mengyun.tcctransaction.api.TransactionContext;
  7 +import org.mengyun.tcctransaction.api.TransactionStatus;
  8 +import org.mengyun.tcctransaction.api.TransactionXid;
  9 +import org.mengyun.tcctransaction.api.UuidUtils;
  10 +import org.mengyun.tcctransaction.api.annotation.Compensable;
  11 +import org.mengyun.tcctransaction.interceptor.invoke.InvocationContext;
  12 +import org.mengyun.tcctransaction.interceptor.invoke.Terminator;
  13 +import org.mengyun.tcctransaction.interceptor.utils.CompensableMethodUtils;
  14 +import org.mengyun.tcctransaction.interceptor.utils.MethodType;
  15 +import org.mengyun.tcctransaction.interceptor.utils.ReflectionUtils;
  16 +import org.mengyun.tcctransaction.repository.TransactionRepository;
  17 +import org.mengyun.tcctransaction.support.TransactionConfigurator;
  18 +import org.slf4j.Logger;
  19 +import org.slf4j.LoggerFactory;
  20 +
  21 +import java.lang.reflect.Method;
  22 +
  23 +/**
  24 + * Created by changmingxie on 11/8/15.
  25 + * 资源协调拦截器。
  26 + */
  27 +public class ResourceCoordinatorInterceptor {
  28 + /** 日志记录器 */
  29 + private static final Logger LOG = LoggerFactory.getLogger(ResourceCoordinatorInterceptor.class);
  30 +
  31 + /** 事务配置器 */
  32 + private TransactionConfigurator transactionConfigurator;
  33 + public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
  34 + this.transactionConfigurator = transactionConfigurator;
  35 + }
  36 +
  37 + /**
  38 + * 拦截事务上下文方法.
  39 + * @param pjp
  40 + * @throws Throwable
  41 + */
  42 + public Object interceptTransactionContextMethod(ProceedingJoinPoint pjp) throws Throwable {
  43 + LOG.debug("==>ResourceCoordinatorInterceptor interceptTransactionContextMethod(ProceedingJoinPoint pjp)");
  44 + // 获取当前事务
  45 + Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction();
  46 +
  47 + // Trying(判断是否Try阶段的事务)
  48 + if (transaction != null && transaction.getStatus().equals(TransactionStatus.TRYING)) {
  49 + LOG.debug("==>TransactionStatus:" + transaction.getStatus().toString());
  50 + // 从参数获取事务上下文
  51 + TransactionContext transactionContext = CompensableMethodUtils.getTransactionContextFromArgs(pjp.getArgs());
  52 + // 获取事务补偿注解
  53 + Compensable compensable = getCompensable(pjp);
  54 + // 计算方法类型
  55 + MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, compensable != null ? true : false);
  56 + LOG.debug("==>methodType:" + methodType.toString());
  57 +
  58 + switch (methodType) {
  59 + case ROOT:
  60 + generateAndEnlistRootParticipant(pjp); // 生成和登记根参与者
  61 + break;
  62 + case CONSUMER:
  63 + generateAndEnlistConsumerParticipant(pjp); // 生成并登记消费者的参与者
  64 + break;
  65 + case PROVIDER:
  66 + generateAndEnlistProviderParticipant(pjp); // 生成并登记服务提供者的参与者
  67 + break;
  68 + }
  69 + }
  70 +
  71 + LOG.debug("==>pjp.proceed(pjp.getArgs())");
  72 + return pjp.proceed(pjp.getArgs());
  73 + }
  74 +
  75 + /**
  76 + * 生成和登记根参与者.
  77 + * @param pjp
  78 + * @return
  79 + */
  80 + private Participant generateAndEnlistRootParticipant(ProceedingJoinPoint pjp) {
  81 + LOG.debug("==>ResourceCoordinatorInterceptor generateAndEnlistRootParticipant(ProceedingJoinPoint pjp)");
  82 + MethodSignature signature = (MethodSignature) pjp.getSignature();
  83 + Method method = signature.getMethod();
  84 + Compensable compensable = getCompensable(pjp);
  85 + String confirmMethodName = compensable.confirmMethod(); // 确认方法
  86 + String cancelMethodName = compensable.cancelMethod(); // 取消方法
  87 +
  88 + Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // 获取当前事务
  89 +
  90 + TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); // 获取事务Xid
  91 + LOG.debug("==>TransactionXid:" + UuidUtils.byteArrayToUUID(xid.getGlobalTransactionId()).toString()
  92 + + "|" + UuidUtils.byteArrayToUUID(xid.getBranchQualifier()).toString());
  93 +
  94 + Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());
  95 +
  96 + // 构建确认方法的提交上下文
  97 + InvocationContext confirmInvocation = new InvocationContext(targetClass,
  98 + confirmMethodName,
  99 + method.getParameterTypes(), pjp.getArgs());
  100 +
  101 + // 构建取消方法的提交上下文
  102 + InvocationContext cancelInvocation = new InvocationContext(targetClass,
  103 + cancelMethodName,
  104 + method.getParameterTypes(), pjp.getArgs());
  105 +
  106 + // 构建参与者对像
  107 + Participant participant =
  108 + new Participant(
  109 + xid,
  110 + new Terminator(confirmInvocation, cancelInvocation));
  111 +
  112 + transaction.enlistParticipant(participant); // 加入参与者
  113 +
  114 + TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
  115 + transactionRepository.update(transaction); // 更新事务
  116 +
  117 + return participant;
  118 + }
  119 +
  120 + /**
  121 + * 生成并登记消费者的参与者
  122 + * @param pjp
  123 + * @return
  124 + */
  125 + private Participant generateAndEnlistConsumerParticipant(ProceedingJoinPoint pjp) {
  126 + LOG.debug("==>ResourceCoordinatorInterceptor generateAndEnlistConsumerParticipant(ProceedingJoinPoint pjp)");
  127 + MethodSignature signature = (MethodSignature) pjp.getSignature();
  128 + Method method = signature.getMethod();
  129 +
  130 + Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // 获取当前事务
  131 +
  132 + TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); // 获取事务Xid
  133 + LOG.debug("==>TransactionXid:" + UuidUtils.byteArrayToUUID(xid.getGlobalTransactionId()).toString()
  134 + + "|" + UuidUtils.byteArrayToUUID(xid.getBranchQualifier()).toString());
  135 +
  136 + // 获取事务上下文参数的位置
  137 + int position = CompensableMethodUtils.getTransactionContextParamPosition(((MethodSignature) pjp.getSignature()).getParameterTypes());
  138 +
  139 + // 给服务接口的TransactionContext参数设值
  140 + pjp.getArgs()[position] = new TransactionContext(xid, transaction.getStatus().getId()); // 构建事务上下文
  141 +
  142 + Object[] tryArgs = pjp.getArgs(); // 获取服务接口参数
  143 + Object[] confirmArgs = new Object[tryArgs.length]; // 确认提交参数
  144 + Object[] cancelArgs = new Object[tryArgs.length]; // 取消提交参数
  145 +
  146 + System.arraycopy(tryArgs, 0, confirmArgs, 0, tryArgs.length); // 数组拷贝
  147 + confirmArgs[position] = new TransactionContext(xid, TransactionStatus.CONFIRMING.getId()); // 构建事务确认上下文
  148 +
  149 + System.arraycopy(tryArgs, 0, cancelArgs, 0, tryArgs.length); // 数组拷贝
  150 + cancelArgs[position] = new TransactionContext(xid, TransactionStatus.CANCELLING.getId()); // 构建事务取消上下文
  151 +
  152 + Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());
  153 +
  154 + // 构建确认方法的提交上下文
  155 + InvocationContext confirmInvocation = new InvocationContext(targetClass, method.getName(), method.getParameterTypes(), confirmArgs);
  156 + // 构建取消方法的提交上下文
  157 + InvocationContext cancelInvocation = new InvocationContext(targetClass, method.getName(), method.getParameterTypes(), cancelArgs);
  158 +
  159 + // 构建参与者对像
  160 + Participant participant =
  161 + new Participant(
  162 + xid,
  163 + new Terminator(confirmInvocation, cancelInvocation));
  164 +
  165 + transaction.enlistParticipant(participant); // 加入到参与者
  166 +
  167 + TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
  168 +
  169 + transactionRepository.update(transaction); // 更新事务
  170 +
  171 + return participant;
  172 + }
  173 +
  174 + /**
  175 + * 生成并登记服务提供者的参与者
  176 + * @param pjp
  177 + * @return
  178 + */
  179 + private Participant generateAndEnlistProviderParticipant(ProceedingJoinPoint pjp) {
  180 +
  181 + MethodSignature signature = (MethodSignature) pjp.getSignature();
  182 + Method method = signature.getMethod();
  183 +
  184 + Compensable compensable = getCompensable(pjp);
  185 +
  186 + String confirmMethodName = compensable.confirmMethod();
  187 + String cancelMethodName = compensable.cancelMethod();
  188 +
  189 + Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction();
  190 +
  191 + TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId());
  192 + LOG.debug("==>TransactionXid:" + UuidUtils.byteArrayToUUID(xid.getGlobalTransactionId()).toString()
  193 + + "|" + UuidUtils.byteArrayToUUID(xid.getBranchQualifier()).toString());
  194 +
  195 + Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());
  196 +
  197 + // 构建确认方法的提交上下文
  198 + InvocationContext confirmInvocation = new InvocationContext(targetClass, confirmMethodName,
  199 + method.getParameterTypes(), pjp.getArgs());
  200 +
  201 + // 构建取消方法的提交上下文
  202 + InvocationContext cancelInvocation = new InvocationContext(targetClass, cancelMethodName,
  203 + method.getParameterTypes(), pjp.getArgs());
  204 +
  205 + // 事务的ID不变,参与者的分支ID是新生成的
  206 + Participant participant =
  207 + new Participant(
  208 + xid,
  209 + new Terminator(confirmInvocation, cancelInvocation));
  210 +
  211 + transaction.enlistParticipant(participant);
  212 +
  213 + TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
  214 + transactionRepository.update(transaction);
  215 +
  216 + return participant;
  217 + }
  218 +
  219 + /**
  220 + * 根据切点,获取事务注解.
  221 + * @param pjp
  222 + * @return
  223 + */
  224 + private Compensable getCompensable(ProceedingJoinPoint pjp) {
  225 + LOG.debug("==>ResourceCoordinatorInterceptor getCompensable(ProceedingJoinPoint pjp)");
  226 + MethodSignature signature = (MethodSignature) pjp.getSignature(); // 获取签名
  227 + Method method = signature.getMethod(); // 获取方法
  228 +
  229 + Compensable compensable = method.getAnnotation(Compensable.class); // 获取注解
  230 +
  231 + if (compensable == null) {
  232 + Method targetMethod = null;
  233 + try {
  234 + // 获取目标方法
  235 + targetMethod = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());
  236 +
  237 + if (targetMethod != null) {
  238 + compensable = targetMethod.getAnnotation(Compensable.class);
  239 + }
  240 +
  241 + } catch (NoSuchMethodException e) {
  242 + compensable = null;
  243 + }
  244 +
  245 + }
  246 + return compensable;
  247 + }
  248 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/invoke/InvocationContext.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/invoke/InvocationContext.java
  1 +package org.mengyun.tcctransaction.interceptor.invoke;
  2 +
  3 +import java.io.Serializable;
  4 +
  5 +/**
  6 + * Created by changmingxie on 11/9/15.
  7 + * 方法调用上下文。
  8 + */
  9 +public class InvocationContext implements Serializable {
  10 + private static final long serialVersionUID = -7969140711432461165L;
  11 + private Class targetClass;
  12 +
  13 + private String methodName;
  14 +
  15 + private Class[] parameterTypes;
  16 +
  17 + private Object[] args;
  18 +
  19 + public InvocationContext() {
  20 +
  21 + }
  22 +
  23 + public InvocationContext(Class targetClass, String methodName, Class[] parameterTypes, Object... args) {
  24 + this.methodName = methodName;
  25 + this.parameterTypes = parameterTypes;
  26 + this.targetClass = targetClass;
  27 + this.args = args;
  28 + }
  29 +
  30 + public Object[] getArgs() {
  31 + return args;
  32 + }
  33 +
  34 + public Class getTargetClass() {
  35 + return targetClass;
  36 + }
  37 +
  38 + public String getMethodName() {
  39 + return methodName;
  40 + }
  41 +
  42 + public Class[] getParameterTypes() {
  43 + return parameterTypes;
  44 + }
  45 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/invoke/Terminator.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/invoke/Terminator.java
  1 +package org.mengyun.tcctransaction.interceptor.invoke;
  2 +
  3 +import com.google.common.base.Strings;
  4 +import org.mengyun.tcctransaction.exception.SystemException;
  5 +import org.mengyun.tcctransaction.support.BeanFactoryAdapter;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +
  9 +import java.io.Serializable;
  10 +import java.lang.reflect.Method;
  11 +
  12 +/**
  13 + * Created by changmingxie on 10/30/15.
  14 + * 终结者。
  15 + */
  16 +public class Terminator implements Serializable {
  17 + private static final long serialVersionUID = -164958655471605778L;
  18 +
  19 + /** 日志记录器 */
  20 + private static final Logger LOG = LoggerFactory.getLogger(Terminator.class);
  21 +
  22 + /** confirm方法调用上下文 */
  23 + private InvocationContext confirmInvocationContext;
  24 +
  25 + /** cancel方法调用上下文 */
  26 + private InvocationContext cancelInvocationContext;
  27 +
  28 + public Terminator() { }
  29 +
  30 + /**
  31 + * 构建终结者对像.
  32 + * @param confirmInvocationContext
  33 + * @param cancelInvocationContext
  34 + */
  35 + public Terminator(InvocationContext confirmInvocationContext, InvocationContext cancelInvocationContext) {
  36 + this.confirmInvocationContext = confirmInvocationContext;
  37 + this.cancelInvocationContext = cancelInvocationContext;
  38 + }
  39 +
  40 + /**
  41 + * 提交参与者事务(在Participant中调用).
  42 + */
  43 + public void commit() {
  44 + LOG.debug("==>Terminator commit invoke");
  45 + invoke(confirmInvocationContext);
  46 + }
  47 +
  48 + /**
  49 + * 回滚参与者事务(在Participant中调用).
  50 + */
  51 + public void rollback() {
  52 + LOG.debug("==>Terminator rollback invoke");
  53 + invoke(cancelInvocationContext);
  54 + }
  55 +
  56 + /**
  57 + * 根据调用上下文,获取目标方法并执行方法调用.
  58 + * @param invocationContext
  59 + * @return
  60 + */
  61 + private Object invoke(InvocationContext invocationContext) {
  62 +
  63 + if (!Strings.isNullOrEmpty(invocationContext.getMethodName())) {
  64 +
  65 + LOG.debug("==>Terminator invoke " + invocationContext.getTargetClass().getName() + "." + invocationContext.getMethodName());
  66 +
  67 + try {
  68 + Object target = BeanFactoryAdapter.getBean(invocationContext.getTargetClass());
  69 +
  70 + if (target == null && !invocationContext.getTargetClass().isInterface()) {
  71 + target = invocationContext.getTargetClass().newInstance();
  72 + }
  73 +
  74 + Method method = null;
  75 + // 找到要调用的目标方法
  76 + method = target.getClass().getMethod(invocationContext.getMethodName(), invocationContext.getParameterTypes());
  77 +
  78 + // 调用服务方法,被再次被TccTransactionContextAspect和ResourceCoordinatorInterceptor拦截,但因为事务状态已经不再是TRYING了,所以直接执行远程服务
  79 + return method.invoke(target, invocationContext.getArgs()); // 调用服务方法
  80 +
  81 + } catch (Exception e) {
  82 + throw new SystemException(e);
  83 + }
  84 + }
  85 + return null;
  86 + }
  87 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/utils/CompensableMethodUtils.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/utils/CompensableMethodUtils.java
  1 +package org.mengyun.tcctransaction.interceptor.utils;
  2 +
  3 +import org.mengyun.tcctransaction.api.TransactionContext;
  4 +
  5 +/**
  6 + * Created by changmingxie on 11/21/15.
  7 + * 可补偿方法工具类。
  8 + */
  9 +public class CompensableMethodUtils {
  10 + /**
  11 + * 计算方法类型.
  12 + * @param transactionContext
  13 + * @param isCompensable
  14 + * @return
  15 + */
  16 + public static MethodType calculateMethodType(TransactionContext transactionContext, boolean isCompensable) {
  17 +
  18 + if (transactionContext == null && isCompensable) {
  19 + // 没有事务上下文信息,并且方法有事务注解的,为可补偿事务根方法(也就是事务发起者)
  20 + //isRootTransactionMethod
  21 + return MethodType.ROOT;
  22 + } else if (transactionContext == null && !isCompensable) {
  23 + // 没有事务上下文信息,并且方法没有事务注解的,为可补偿事务服务消费者(参考者)方法(一般为被调用的服务接口)
  24 + //isSoaConsumer
  25 + return MethodType.CONSUMER;
  26 + } else if (transactionContext != null && isCompensable) {
  27 + // 有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法)
  28 + //isSoaProvider
  29 + return MethodType.PROVIDER;
  30 + } else {
  31 + return MethodType.NORMAL;
  32 + }
  33 + }
  34 +
  35 + /**
  36 + * 获取事务上下文参数的位置.
  37 + * @param parameterTypes
  38 + * @return
  39 + */
  40 + public static int getTransactionContextParamPosition(Class<?>[] parameterTypes) {
  41 +
  42 + int i = -1;
  43 +
  44 + for (i = 0; i < parameterTypes.length; i++) {
  45 + if (parameterTypes[i].equals(org.mengyun.tcctransaction.api.TransactionContext.class)) {
  46 + break;
  47 + }
  48 + }
  49 + return i;
  50 + }
  51 +
  52 + /**
  53 + * 从参数获取事务上下文.
  54 + * @param args
  55 + * @return
  56 + */
  57 + public static TransactionContext getTransactionContextFromArgs(Object[] args) {
  58 +
  59 + TransactionContext transactionContext = null;
  60 +
  61 + for (Object arg : args) {
  62 + if (arg != null && org.mengyun.tcctransaction.api.TransactionContext.class.isAssignableFrom(arg.getClass())) {
  63 +
  64 + transactionContext = (org.mengyun.tcctransaction.api.TransactionContext) arg;
  65 + }
  66 + }
  67 +
  68 + return transactionContext;
  69 + }
  70 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/utils/MethodType.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/utils/MethodType.java
  1 +package org.mengyun.tcctransaction.interceptor.utils;
  2 +
  3 +/**
  4 + * Created by changmingxie on 11/11/15.
  5 + * 方法类型。
  6 + */
  7 +public enum MethodType {
  8 +
  9 + /**
  10 + * 根
  11 + */
  12 + ROOT,
  13 +
  14 + /**
  15 + * 消费者
  16 + */
  17 + CONSUMER,
  18 +
  19 + /**
  20 + * 提供者
  21 + */
  22 + PROVIDER,
  23 +
  24 + /**
  25 + * 常规
  26 + */
  27 + NORMAL;
  28 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/utils/ReflectionUtils.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/interceptor/utils/ReflectionUtils.java
  1 +package org.mengyun.tcctransaction.interceptor.utils;
  2 +
  3 +import java.lang.reflect.Method;
  4 +
  5 +/**
  6 + * Created by changmingxie on 11/22/15.
  7 + */
  8 +public class ReflectionUtils {
  9 + public static Class getDeclaringType(Class aClass, String methodName, Class<?>[] parameterTypes) {
  10 +
  11 + Method method = null;
  12 +
  13 +
  14 + Class findClass = aClass;
  15 +
  16 + do {
  17 + Class[] clazzes = findClass.getInterfaces();
  18 +
  19 + for (Class clazz : clazzes) {
  20 +
  21 + try {
  22 + method = clazz.getDeclaredMethod(methodName, parameterTypes);
  23 + } catch (NoSuchMethodException e) {
  24 + method = null;
  25 + }
  26 +
  27 + if (method != null) {
  28 + return clazz;
  29 + }
  30 + }
  31 +
  32 + findClass = findClass.getSuperclass();
  33 +
  34 + } while (!findClass.equals(Object.class));
  35 +
  36 + return aClass;
  37 + }
  38 +
  39 + public static Object getNullValue(Class type) {
  40 +
  41 + if (boolean.class.equals(type)) {
  42 + return false;
  43 + } else if (byte.class.equals(type)) {
  44 + return 0;
  45 + } else if (short.class.equals(type)) {
  46 + return 0;
  47 + } else if (int.class.equals(type)) {
  48 + return 0;
  49 + } else if (long.class.equals(type)) {
  50 + return 0;
  51 + } else if (float.class.equals(type)) {
  52 + return 0;
  53 + } else if (double.class.equals(type)) {
  54 + return 0;
  55 + }
  56 +
  57 + return null;
  58 + }
  59 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/recover/RecoverConfig.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/recover/RecoverConfig.java
  1 +package org.mengyun.tcctransaction.recover;
  2 +
  3 +/**
  4 + * 事务恢复配置接口.
  5 + * Created by changming.xie on 6/1/16.
  6 + */
  7 +public interface RecoverConfig {
  8 + /**
  9 + * 获取最大重试次数
  10 + * @return
  11 + */
  12 + int getMaxRetryCount();
  13 +
  14 + /**
  15 + * 获取需要执行事务恢复的持续时间.
  16 + * @return
  17 + */
  18 + int getRecoverDuration();
  19 +
  20 + /**
  21 + * 获取定时任务规则表达式.
  22 + * @return
  23 + */
  24 + String getCronExpression();
  25 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/recover/TransactionRecovery.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/recover/TransactionRecovery.java
  1 +package org.mengyun.tcctransaction.recover;
  2 +
  3 +import org.mengyun.tcctransaction.Transaction;
  4 +import org.mengyun.tcctransaction.TransactionType;
  5 +import org.mengyun.tcctransaction.api.TransactionStatus;
  6 +import org.mengyun.tcctransaction.repository.TransactionRepository;
  7 +import org.mengyun.tcctransaction.support.TransactionConfigurator;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +
  11 +import java.util.ArrayList;
  12 +import java.util.Calendar;
  13 +import java.util.Date;
  14 +import java.util.List;
  15 +
  16 +/**
  17 + * Created by changmingxie on 11/10/15.
  18 + * 事务恢复.
  19 + */
  20 +public class TransactionRecovery {
  21 + /** 日志记录器 */
  22 + private static final Logger LOG = LoggerFactory.getLogger(TransactionRecovery.class);
  23 +
  24 + /** TCC事务配置器 */
  25 + private TransactionConfigurator transactionConfigurator;
  26 + public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
  27 + this.transactionConfigurator = transactionConfigurator;
  28 + }
  29 +
  30 + /**
  31 + * 启动事务恢复操作(被RecoverScheduledJob定时任务调用).
  32 + */
  33 + public void startRecover() {
  34 + List<Transaction> transactions = loadErrorTransactions(); // 找出所有执行错误的事务信息
  35 + recoverErrorTransactions(transactions);
  36 + }
  37 +
  38 + /**
  39 + * 找出所有执行错误的事务信息
  40 + * @return
  41 + */
  42 + private List<Transaction> loadErrorTransactions() {
  43 +
  44 + TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
  45 +
  46 + long currentTimeInMillis = Calendar.getInstance().getTimeInMillis();
  47 +
  48 + // 找出相关时间内的异常ROOT类型的事务
  49 + List<Transaction> transactions = transactionRepository.findAllUnmodifiedSince(
  50 + new Date(currentTimeInMillis - transactionConfigurator.getRecoverConfig().getRecoverDuration() * 1000),
  51 + TransactionType.ROOT);
  52 +
  53 + List<Transaction> recoverTransactions = new ArrayList<>();
  54 +
  55 + for (Transaction transaction : transactions) {
  56 + // 检验记录是否已经被修改(版本校验)
  57 + int result = transactionRepository.update(transaction);
  58 +
  59 + if (result > 0) {
  60 + recoverTransactions.add(transaction);
  61 + }
  62 + }
  63 +
  64 + // 日志输出,调试用
  65 + if (!transactions.isEmpty()){
  66 + LOG.debug("==>TransactionRecovery loadErrorTransactions transactions size:" + transactions.size());
  67 + }
  68 +
  69 + return recoverTransactions;
  70 + }
  71 +
  72 +
  73 + /**
  74 + * 恢复错误的事务.
  75 + * @param transactions
  76 + */
  77 + private void recoverErrorTransactions(List<Transaction> transactions) {
  78 +
  79 +
  80 + for (Transaction transaction : transactions) {
  81 +
  82 + if (transaction.getRetriedCount() > transactionConfigurator.getRecoverConfig().getMaxRetryCount()) {
  83 + // 超过次数的,跳过
  84 + LOG.error(String.format(
  85 + "TransactionRecovery recover failed with max retry count,will not try again. txid:%s, status:%s,retried count:%d",
  86 + transaction.getXid(), transaction.getStatus().getId(), transaction.getRetriedCount()));
  87 + continue;
  88 + }
  89 +
  90 + try {
  91 + transaction.addRetriedCount(); // 重试次数+1
  92 +
  93 + if (transaction.getStatus().equals(TransactionStatus.CONFIRMING)) {
  94 + // 如果是CONFIRMING(2)状态,则将事务往前执行
  95 + transaction.changeStatus(TransactionStatus.CONFIRMING);
  96 + transactionConfigurator.getTransactionRepository().update(transaction);
  97 + transaction.commit();
  98 +
  99 + } else {
  100 + // 其他情况,把事务状态改为CANCELLING(3),然后执行回滚
  101 + transaction.changeStatus(TransactionStatus.CANCELLING);
  102 + transactionConfigurator.getTransactionRepository().update(transaction);
  103 + transaction.rollback();
  104 + }
  105 +
  106 + // 其他情况下,超时没处理的事务日志直接删除
  107 + transactionConfigurator.getTransactionRepository().delete(transaction);
  108 + } catch (Throwable e) {
  109 + LOG.warn(String.format(
  110 + "TransactionRecovery recover failed, txid:%s, status:%s,retried count:%d",
  111 + transaction.getXid(), transaction.getStatus().getId(), transaction.getRetriedCount()), e);
  112 + }
  113 + }
  114 + }
  115 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/TransactionRepository.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/TransactionRepository.java
  1 +package org.mengyun.tcctransaction.repository;
  2 +
  3 +import org.mengyun.tcctransaction.Transaction;
  4 +import org.mengyun.tcctransaction.TransactionType;
  5 +import org.mengyun.tcctransaction.api.TransactionXid;
  6 +
  7 +import java.util.Date;
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * Created by changmingxie on 11/12/15.
  12 + * 事务库接口(事务日志操作).
  13 + */
  14 +public interface TransactionRepository {
  15 + /**
  16 + * 创建事务日志记录.
  17 + * @param transaction
  18 + */
  19 + int create(Transaction transaction);
  20 +
  21 + /**
  22 + * 更新事务日志记录.
  23 + * @param transaction
  24 + */
  25 + int update(Transaction transaction);
  26 +
  27 + /**
  28 + * 删除事务日志记录.
  29 + * @param transaction
  30 + */
  31 + int delete(Transaction transaction);
  32 +
  33 + /**
  34 + * 根据xid查找事务日志记录.
  35 + * @param xid
  36 + * @return
  37 + */
  38 + Transaction findByXid(TransactionXid xid);
  39 +
  40 + /**
  41 + * 找出所有未处理事务日志(从某一时间点开始).
  42 + * @return
  43 + */
  44 + List<Transaction> findAllUnmodifiedSince(Date date, TransactionType transactionType);
  45 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/impl/CachableTransactionRepository.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/impl/CachableTransactionRepository.java
  1 +package org.mengyun.tcctransaction.repository.impl;
  2 +
  3 +import com.google.common.cache.Cache;
  4 +import com.google.common.cache.CacheBuilder;
  5 +import org.mengyun.tcctransaction.Transaction;
  6 +import org.mengyun.tcctransaction.TransactionType;
  7 +import org.mengyun.tcctransaction.api.TransactionXid;
  8 +import org.mengyun.tcctransaction.exception.OptimisticLockException;
  9 +import org.mengyun.tcctransaction.repository.TransactionRepository;
  10 +import org.slf4j.Logger;
  11 +import org.slf4j.LoggerFactory;
  12 +
  13 +import javax.transaction.xa.Xid;
  14 +import java.util.Date;
  15 +import java.util.List;
  16 +import java.util.concurrent.TimeUnit;
  17 +
  18 +/**
  19 + * Created by changmingxie on 10/30/15.
  20 + * 缓存事务库。
  21 + */
  22 +public abstract class CachableTransactionRepository implements TransactionRepository {
  23 + /** 日志记录器 */
  24 + private final static Logger LOG = LoggerFactory.getLogger(CachableTransactionRepository.class);
  25 +
  26 + /** 缓存到期时间(以秒为单位) */
  27 + private int expireDuration = 300;
  28 + public final void setExpireDuration(int durationInSeconds) {
  29 + this.expireDuration = durationInSeconds;
  30 + }
  31 + /** 事务日志记录缓存<Xid, Transaction> */
  32 + private Cache<Xid, Transaction> transactionXidCompensableTransactionCache;
  33 + public CachableTransactionRepository() {
  34 + transactionXidCompensableTransactionCache = CacheBuilder.newBuilder()
  35 + .expireAfterAccess(expireDuration, TimeUnit.SECONDS)
  36 + .maximumSize(1000)
  37 + .build();
  38 + }
  39 +
  40 + /**
  41 + * 放入缓存.
  42 + * @param transaction
  43 + */
  44 + protected void putToCache(Transaction transaction) {
  45 + transactionXidCompensableTransactionCache.put(transaction.getXid(), transaction);
  46 + }
  47 + /**
  48 + * 从缓存中删除.
  49 + * @param transaction
  50 + */
  51 + protected void removeFromCache(Transaction transaction) {
  52 + transactionXidCompensableTransactionCache.invalidate(transaction.getXid());
  53 + }
  54 +
  55 + /**
  56 + * 从缓存中查找.
  57 + * @param transactionXid
  58 + * @return
  59 + */
  60 + protected Transaction findFromCache(TransactionXid transactionXid) {
  61 + return transactionXidCompensableTransactionCache.getIfPresent(transactionXid);
  62 + }
  63 +
  64 + @Override
  65 + public int create(Transaction transaction) {
  66 + LOG.debug("==>create(Transaction transaction)");
  67 + int result = doCreate(transaction);
  68 + if (result > 0) {
  69 + putToCache(transaction);
  70 + }
  71 + return result;
  72 + }
  73 +
  74 + @Override
  75 + public int update(Transaction transaction) {
  76 + LOG.debug("==>update(Transaction transaction)");
  77 + int result = doUpdate(transaction);
  78 + if (result > 0) {
  79 + putToCache(transaction);
  80 + } else {
  81 + throw new OptimisticLockException();
  82 + }
  83 + return result;
  84 + }
  85 +
  86 + @Override
  87 + public int delete(Transaction transaction) {
  88 + LOG.debug("==>delete(Transaction transaction)");
  89 + int result = doDelete(transaction);
  90 + if (result > 0) {
  91 + removeFromCache(transaction);
  92 + }
  93 + return result;
  94 + }
  95 +
  96 + @Override
  97 + public Transaction findByXid(TransactionXid xid) {
  98 + Transaction transaction = findFromCache(xid);
  99 + if (transaction == null) {
  100 + transaction = doFindOne(xid);
  101 + if (transaction != null) {
  102 + putToCache(transaction);
  103 + }
  104 + }
  105 + return transaction;
  106 + }
  107 +
  108 + @Override
  109 + public List<Transaction> findAllUnmodifiedSince(Date date, TransactionType transactionType) {
  110 + List<Transaction> transactions = doFindAllUnmodifiedSince(date, transactionType);
  111 + for (Transaction transaction : transactions) {
  112 + putToCache(transaction);
  113 + }
  114 + return transactions;
  115 + }
  116 +
  117 + //-------------------- 需要覆写的方法 --------------------//
  118 + protected abstract int doCreate(Transaction transaction);
  119 + protected abstract int doUpdate(Transaction transaction);
  120 + protected abstract int doDelete(Transaction transaction);
  121 + protected abstract Transaction doFindOne(Xid xid);
  122 + protected abstract List<Transaction> doFindAllUnmodifiedSince(Date date, TransactionType transactionType);
  123 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/impl/JdbcTransactionRepository.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/repository/impl/JdbcTransactionRepository.java
  1 +package org.mengyun.tcctransaction.repository.impl;
  2 +
  3 +import com.google.common.base.Strings;
  4 +import org.mengyun.tcctransaction.Transaction;
  5 +import org.mengyun.tcctransaction.TransactionType;
  6 +import org.mengyun.tcctransaction.exception.TransactionIOException;
  7 +import org.mengyun.tcctransaction.serializer.ObjectSerializer;
  8 +import org.mengyun.tcctransaction.serializer.impl.JdkSerializationSerializer;
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +
  12 +import javax.sql.DataSource;
  13 +import javax.transaction.xa.Xid;
  14 +import java.sql.*;
  15 +import java.util.ArrayList;
  16 +import java.util.Date;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * Created by changmingxie on 10/30/15.
  21 + * JDBC事务库(在应用服务中实例化并注入数据源)。
  22 + */
  23 +public class JdbcTransactionRepository extends CachableTransactionRepository {
  24 + /** 日志记录器 */
  25 + private final static Logger LOG = LoggerFactory.getLogger(JdbcTransactionRepository.class);
  26 +
  27 + /** 域名(标识事务名) */
  28 + private String domain;
  29 + public String getDomain() {
  30 + return domain;
  31 + }
  32 + public void setDomain(String domain) {
  33 + this.domain = domain;
  34 + }
  35 +
  36 + /** 表名后缀 */
  37 + private String tbSuffix;
  38 + public String getTbSuffix() {
  39 + return tbSuffix;
  40 + }
  41 + public void setTbSuffix(String tbSuffix) {
  42 + this.tbSuffix = tbSuffix;
  43 + }
  44 +
  45 + /** 事务对象序列器 */
  46 + private ObjectSerializer serializer = new JdkSerializationSerializer();
  47 + public void setSerializer(ObjectSerializer serializer) {
  48 + this.serializer = serializer;
  49 + }
  50 +
  51 + /** 数据源 */
  52 + private DataSource dataSource;
  53 + public DataSource getDataSource() {
  54 + return dataSource;
  55 + }
  56 + public void setDataSource(DataSource dataSource) {
  57 + this.dataSource = dataSource;
  58 + }
  59 +
  60 + //-------------------------- 覆写的方法 ---------------------------//
  61 + protected Connection getConnection() {
  62 + try {
  63 + return this.dataSource.getConnection();
  64 + } catch (SQLException e) {
  65 + throw new TransactionIOException(e);
  66 + }
  67 + }
  68 +
  69 + protected void releaseConnection(Connection con) {
  70 + try {
  71 + if (con != null && !con.isClosed()) {
  72 + con.close();
  73 + }
  74 + } catch (SQLException e) {
  75 + throw new TransactionIOException(e);
  76 + }
  77 + }
  78 +
  79 + private void closeStatement(Statement stmt) {
  80 + try {
  81 + if (stmt != null && !stmt.isClosed()) {
  82 + stmt.close();
  83 + }
  84 + } catch (Exception ex) {
  85 + throw new TransactionIOException(ex);
  86 + }
  87 + }
  88 +
  89 + private String getTableName() {
  90 + if (Strings.isNullOrEmpty(tbSuffix)) {
  91 + return "TCC_TRANSACTION";
  92 + } else {
  93 + return "TCC_TRANSACTION" + tbSuffix;
  94 + }
  95 + }
  96 +
  97 + private final static String INSERT_SQL_Template =
  98 + "INSERT INTO %s" +
  99 + "(GLOBAL_TX_ID,BRANCH_QUALIFIER,TRANSACTION_TYPE,CONTENT,STATUS,RETRIED_COUNT,CREATE_TIME,LAST_UPDATE_TIME,VERSION,DOMAIN) " +
  100 + "VALUES (?,?,?,?,?,?,?,?,?,?)";
  101 + @Override
  102 + protected int doCreate(Transaction transaction) {
  103 + LOG.debug("==>JdbcTransactionRepository.doCreate(Transaction transaction)");
  104 +
  105 + Connection connection = null;
  106 + PreparedStatement stmt = null;
  107 +
  108 + try {
  109 + connection = this.getConnection();
  110 +
  111 + stmt = connection.prepareStatement(String.format(INSERT_SQL_Template, getTableName()));
  112 + stmt.setBytes(1, transaction.getXid().getGlobalTransactionId()); // GLOBAL_TX_ID(全局事务ID)
  113 + stmt.setBytes(2, transaction.getXid().getBranchQualifier()); // BRANCH_QUALIFIER(分支限定符)
  114 + stmt.setInt(3, transaction.getTransactionType().getId()); // TRANSACTION_TYPE(事务类型,主事务:1,分支事务:2)
  115 + stmt.setBytes(4, serializer.serialize(transaction)); // CONTENT(事务内容序列化)
  116 + stmt.setInt(5, transaction.getStatus().getId()); // STATUS(事务状态,TRYING(1),CONFIRMING(2),CANCELLING(3))
  117 + stmt.setInt(6, transaction.getRetriedCount()); // RETRIED_COUNT(事务恢复重试次数)
  118 + stmt.setTimestamp(7, new java.sql.Timestamp(transaction.getCreateTime().getTime())); // CREATE_TIME(创建时间)
  119 + stmt.setTimestamp(8, new java.sql.Timestamp(transaction.getLastUpdateTime().getTime())); // LAST_UPDATE_TIME(最后更新时间)
  120 + stmt.setLong(9, transaction.getVersion()); // VERSION(版本号)
  121 + if (Strings.isNullOrEmpty(domain)) {
  122 + stmt.setString(10, null);
  123 + } else {
  124 + stmt.setString(10, domain);
  125 + }
  126 +
  127 + return stmt.executeUpdate();
  128 +
  129 + } catch (SQLException e) {
  130 + throw new TransactionIOException(e);
  131 + } finally {
  132 + closeStatement(stmt);
  133 + this.releaseConnection(connection);
  134 + }
  135 +
  136 + }
  137 +
  138 + private final static String UPDATE_SQL_Template =
  139 + "UPDATE %s " +
  140 + "set CONTENT = ?,STATUS = ?,LAST_UPDATE_TIME = ?, RETRIED_COUNT = ?,VERSION = VERSION+1 " +
  141 + "where GLOBAL_TX_ID = ? AND BRANCH_QUALIFIER = ? AND VERSION = ? %s";
  142 + @Override
  143 + protected int doUpdate(Transaction transaction) {
  144 + LOG.debug("==>JdbcTransactionRepository.doUpdate(Transaction transaction)");
  145 +
  146 + Connection connection = null;
  147 + PreparedStatement stmt = null;
  148 +
  149 + transaction.updateTime();
  150 + transaction.updateVersion();
  151 +
  152 + try {
  153 + connection = this.getConnection();
  154 +
  155 + if (Strings.isNullOrEmpty(domain)) {
  156 + stmt = connection.prepareStatement(String.format(UPDATE_SQL_Template,
  157 + getTableName(), ""));
  158 + } else {
  159 + stmt = connection.prepareStatement(String.format(UPDATE_SQL_Template,
  160 + getTableName(), " AND DOMAIN = ?"));
  161 + }
  162 + stmt.setBytes(1, serializer.serialize(transaction));
  163 + stmt.setInt(2, transaction.getStatus().getId());
  164 + stmt.setTimestamp(3, new Timestamp(transaction.getLastUpdateTime().getTime()));
  165 + stmt.setInt(4, transaction.getRetriedCount());
  166 + stmt.setBytes(5, transaction.getXid().getGlobalTransactionId());
  167 + stmt.setBytes(6, transaction.getXid().getBranchQualifier());
  168 + stmt.setLong(7, transaction.getVersion() - 1);
  169 + if (!Strings.isNullOrEmpty(domain)) {
  170 + stmt.setString(8, domain);
  171 + }
  172 +
  173 + int result = stmt.executeUpdate();
  174 +
  175 + return result;
  176 + } catch (Throwable e) {
  177 + throw new TransactionIOException(e);
  178 + } finally {
  179 + closeStatement(stmt);
  180 + this.releaseConnection(connection);
  181 + }
  182 +
  183 + }
  184 +
  185 + private final static String DELETE_SQL_Template =
  186 + "DELETE FROM %s " +
  187 + "WHERE GLOBAL_TX_ID = ? AND BRANCH_QUALIFIER = ? %s";
  188 + @Override
  189 + protected int doDelete(Transaction transaction) {
  190 + LOG.debug("==>JdbcTransactionRepository.doDelete(Transaction transaction)");
  191 +
  192 + Connection connection = null;
  193 + PreparedStatement stmt = null;
  194 +
  195 + try {
  196 + connection = this.getConnection();
  197 +
  198 + if (Strings.isNullOrEmpty(domain)) {
  199 + stmt = connection.prepareStatement(String.format(DELETE_SQL_Template,
  200 + getTableName(), ""));
  201 + } else {
  202 + stmt = connection.prepareStatement(String.format(DELETE_SQL_Template,
  203 + getTableName(), "AND DOMAIN = ?"));
  204 + }
  205 + stmt.setBytes(1, transaction.getXid().getGlobalTransactionId());
  206 + stmt.setBytes(2, transaction.getXid().getBranchQualifier());
  207 + if (!Strings.isNullOrEmpty(domain)) {
  208 + stmt.setString(3, domain);
  209 + }
  210 +
  211 + return stmt.executeUpdate();
  212 +
  213 + } catch (SQLException e) {
  214 + throw new TransactionIOException(e);
  215 + } finally {
  216 + closeStatement(stmt);
  217 + this.releaseConnection(connection);
  218 + }
  219 +
  220 + }
  221 +
  222 + private final static String SELECT_ONE_SQL_Template =
  223 + "SELECT GLOBAL_TX_ID, BRANCH_QUALIFIER, CONTENT,STATUS,TRANSACTION_TYPE,CREATE_TIME,LAST_UPDATE_TIME,RETRIED_COUNT,VERSION,DOMAIN " +
  224 + "FROM %s " +
  225 + "WHERE GLOBAL_TX_ID = ? AND BRANCH_QUALIFIER = ? %s";
  226 + @Override
  227 + protected Transaction doFindOne(Xid xid) {
  228 + LOG.debug("==>doFindOne xid:" + xid.getGlobalTransactionId());
  229 +
  230 + Connection connection = null;
  231 + PreparedStatement stmt = null;
  232 +
  233 + try {
  234 + connection = this.getConnection();
  235 +
  236 + if (Strings.isNullOrEmpty(domain)) {
  237 + stmt = connection.prepareStatement(String.format(SELECT_ONE_SQL_Template,
  238 + getTableName(), ""));
  239 + } else {
  240 + stmt = connection.prepareStatement(String.format(SELECT_ONE_SQL_Template,
  241 + getTableName(), "AND DOMAIN = ?"));
  242 + }
  243 + stmt.setBytes(1, xid.getGlobalTransactionId());
  244 + stmt.setBytes(2, xid.getBranchQualifier());
  245 + if (!Strings.isNullOrEmpty(domain)) {
  246 + stmt.setString(3, domain);
  247 + }
  248 + ResultSet resultSet = stmt.executeQuery();
  249 + if (resultSet.next()) {
  250 + byte[] transactionBytes = resultSet.getBytes(3);
  251 + Transaction transaction = (Transaction) serializer.deserialize(transactionBytes);
  252 + transaction.setLastUpdateTime(resultSet.getDate(7));
  253 + transaction.setVersion(resultSet.getLong(9));
  254 + transaction.resetRetriedCount(resultSet.getInt(8));
  255 + return transaction;
  256 + } else {
  257 + return null;
  258 + }
  259 +
  260 + } catch (Throwable e) {
  261 + throw new TransactionIOException(e);
  262 + } finally {
  263 + closeStatement(stmt);
  264 + this.releaseConnection(connection);
  265 + }
  266 + }
  267 +
  268 + private final static String SELECT_MULTI_SQL_Template =
  269 + "SELECT GLOBAL_TX_ID, BRANCH_QUALIFIER, CONTENT,STATUS,TRANSACTION_TYPE,CREATE_TIME,LAST_UPDATE_TIME,RETRIED_COUNT,VERSION,DOMAIN " +
  270 + "FROM %s " +
  271 + "WHERE LAST_UPDATE_TIME != ? AND TRANSACTION_TYPE = ? %s";
  272 + @Override
  273 + protected List<Transaction> doFindAllUnmodifiedSince(Date date, TransactionType transactionType) {
  274 + LOG.debug("==>doFindOne date:" + date);
  275 +
  276 + List<Transaction> transactions = new ArrayList<>();
  277 +
  278 + Connection connection = null;
  279 + PreparedStatement stmt = null;
  280 +
  281 + try {
  282 + connection = this.getConnection();
  283 +
  284 + if (Strings.isNullOrEmpty(domain)) {
  285 + stmt = connection.prepareStatement(String.format(SELECT_MULTI_SQL_Template,
  286 + getTableName(), ""));
  287 +
  288 + } else {
  289 + stmt = connection.prepareStatement(String.format(SELECT_MULTI_SQL_Template,
  290 + getTableName(), "AND DOMAIN = ?"));
  291 + }
  292 + stmt.setTimestamp(1, new Timestamp(date.getTime()));
  293 + stmt.setInt(2, transactionType.getId());
  294 + if (!Strings.isNullOrEmpty(domain)) {
  295 + stmt.setString(3, domain);
  296 + }
  297 +
  298 + ResultSet resultSet = stmt.executeQuery();
  299 +
  300 + while (resultSet.next()) {
  301 + byte[] transactionBytes = resultSet.getBytes(3);
  302 + Transaction transaction = (Transaction) serializer.deserialize(transactionBytes);
  303 + transaction.setLastUpdateTime(resultSet.getDate(7));
  304 + transaction.setVersion(resultSet.getLong(9));
  305 + transaction.resetRetriedCount(resultSet.getInt(8));
  306 + transactions.add(transaction);
  307 + }
  308 +
  309 + } catch (Throwable e) {
  310 + throw new TransactionIOException(e);
  311 + } finally {
  312 + closeStatement(stmt);
  313 + this.releaseConnection(connection);
  314 + }
  315 +
  316 + return transactions;
  317 + }
  318 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/serializer/ObjectSerializer.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/serializer/ObjectSerializer.java
  1 +package org.mengyun.tcctransaction.serializer;
  2 +
  3 +/**
  4 + * Created by changming.xie on 7/22/16.
  5 + * 自定义对象序列换接口。
  6 + */
  7 +public interface ObjectSerializer<T> {
  8 + /**
  9 + * 序列化。
  10 + * @param t 对象
  11 + * @return 字节数组
  12 + */
  13 + byte[] serialize(T t);
  14 +
  15 + /**
  16 + * 反序列化。
  17 + * @param bytes 字节数组
  18 + * @return 对象
  19 + */
  20 + T deserialize(byte[] bytes);
  21 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/serializer/impl/JdkSerializationSerializer.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/serializer/impl/JdkSerializationSerializer.java
  1 +package org.mengyun.tcctransaction.serializer.impl;
  2 +
  3 +import org.mengyun.tcctransaction.serializer.ObjectSerializer;
  4 +
  5 +import java.io.*;
  6 +
  7 +/**
  8 + * Created by changming.xie on 7/22/16.
  9 + * java序列化。
  10 + */
  11 +public class JdkSerializationSerializer<T> implements ObjectSerializer<T> {
  12 +
  13 + @Override
  14 + public byte[] serialize(T t) {
  15 + if (t == null) {
  16 + return null;
  17 + } else {
  18 + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
  19 +
  20 + try {
  21 + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
  22 + objectOutputStream.writeObject(t);
  23 + objectOutputStream.flush();
  24 + } catch (IOException exp) {
  25 + throw new IllegalArgumentException("Failed to serialize object of type: " + t.getClass(), exp);
  26 + }
  27 +
  28 + return byteArrayOutputStream.toByteArray();
  29 +
  30 + }
  31 +
  32 + }
  33 +
  34 + @Override
  35 + public T deserialize(byte[] bytes) {
  36 + if (bytes == null) {
  37 + return null;
  38 + } else {
  39 + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
  40 +
  41 + try {
  42 + ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
  43 + return (T) objectInputStream.readObject();
  44 + } catch (IOException exp) {
  45 + throw new IllegalArgumentException("Failed to deserialize object", exp);
  46 + } catch (ClassNotFoundException exp2) {
  47 + throw new IllegalStateException("Failed to deserialize object type", exp2);
  48 + }
  49 + }
  50 + }
  51 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/support/BeanFactory.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/support/BeanFactory.java
  1 +package org.mengyun.tcctransaction.support;
  2 +
  3 +/**
  4 + * Created by changmingxie on 11/20/15.
  5 + */
  6 +public interface BeanFactory {
  7 + Object getBean(Class<?> aClass);
  8 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/support/BeanFactoryAdapter.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/support/BeanFactoryAdapter.java
  1 +package org.mengyun.tcctransaction.support;
  2 +
  3 +/**
  4 + * Created by changmingxie on 11/20/15.
  5 + */
  6 +public class BeanFactoryAdapter {
  7 +
  8 + private static BeanFactory beanFactory;
  9 +
  10 + public static Object getBean(Class<?> aClass) {
  11 + return beanFactory.getBean(aClass);
  12 + }
  13 +
  14 + public static void setBeanFactory(BeanFactory beanFactory) {
  15 + BeanFactoryAdapter.beanFactory = beanFactory;
  16 + }
  17 +}
... ...
tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/support/TransactionConfigurator.java 0 → 100644
  1 +++ a/tcc-transaction-core/src/main/java/org/mengyun/tcctransaction/support/TransactionConfigurator.java
  1 +package org.mengyun.tcctransaction.support;
  2 +
  3 +import org.mengyun.tcctransaction.TransactionManager;
  4 +import org.mengyun.tcctransaction.recover.RecoverConfig;
  5 +import org.mengyun.tcctransaction.repository.TransactionRepository;
  6 +
  7 +/**
  8 + * Created by changmingxie on 11/10/15.
  9 + * 事务配置器接口。
  10 + */
  11 +public interface TransactionConfigurator {
  12 + /**
  13 + * 获取事务管理器.
  14 + * @return
  15 + */
  16 + TransactionManager getTransactionManager();
  17 +
  18 + /**
  19 + * 获取事务库.
  20 + * @return
  21 + */
  22 + TransactionRepository getTransactionRepository();
  23 +
  24 + /**
  25 + * 获取事务恢复配置.
  26 + * @return
  27 + */
  28 + RecoverConfig getRecoverConfig();
  29 +}
... ...
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/Transaction.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/TransactionManager.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/TransactionType.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/exception/CancellingException.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/exception/ConfirmingException.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/exception/NoExistedTransactionException.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/exception/OptimisticLockException.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/exception/SystemException.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/exception/TransactionIOException.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/CompensableTransactionInterceptor$1.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/CompensableTransactionInterceptor.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/Participant.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/ResourceCoordinatorInterceptor$1.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/ResourceCoordinatorInterceptor.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/invoke/InvocationContext.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/invoke/Terminator.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/utils/CompensableMethodUtils.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/utils/MethodType.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/interceptor/utils/ReflectionUtils.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/recover/RecoverConfig.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/recover/TransactionRecovery.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/repository/TransactionRepository.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/repository/impl/CachableTransactionRepository.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/repository/impl/JdbcTransactionRepository.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/serializer/ObjectSerializer.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/serializer/impl/JdkSerializationSerializer.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/support/BeanFactory.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/support/BeanFactoryAdapter.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/classes/org/mengyun/tcctransaction/support/TransactionConfigurator.class 0 → 100644
No preview for this file type
tcc-transaction-core/target/maven-archiver/pom.properties 0 → 100644
  1 +++ a/tcc-transaction-core/target/maven-archiver/pom.properties
  1 +#Generated by Maven
  2 +#Thu Jan 02 11:02:36 CST 2020
  3 +version=1.1.5_comment
  4 +groupId=org.mengyun
  5 +artifactId=tcc-transaction-core
... ...
tcc-transaction-core/target/tcc-transaction-core-1.1.5_comment-sources.jar 0 → 100644
No preview for this file type
tcc-transaction-core/target/tcc-transaction-core-1.1.5_comment.jar 0 → 100644
No preview for this file type
tcc-transaction-spring/pom.xml 0 → 100644
  1 +++ a/tcc-transaction-spring/pom.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <artifactId>tcc-transaction</artifactId>
  7 + <groupId>org.mengyun</groupId>
  8 + <version>1.1.5_comment</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>tcc-transaction-spring</artifactId>
  13 +
  14 + <dependencies>
  15 + <dependency>
  16 + <groupId>org.mengyun</groupId>
  17 + <artifactId>tcc-transaction-api</artifactId>
  18 + </dependency>
  19 + <dependency>
  20 + <groupId>org.mengyun</groupId>
  21 + <artifactId>tcc-transaction-core</artifactId>
  22 + </dependency>
  23 +
  24 + <!-- spring相关 begin -->
  25 + <dependency>
  26 + <groupId>org.springframework</groupId>
  27 + <artifactId>spring-aspects</artifactId>
  28 + </dependency>
  29 + <dependency>
  30 + <groupId>org.springframework</groupId>
  31 + <artifactId>spring-aop</artifactId>
  32 + </dependency>
  33 + <dependency>
  34 + <groupId>org.springframework</groupId>
  35 + <artifactId>spring-jdbc</artifactId>
  36 + </dependency>
  37 + <dependency>
  38 + <groupId>org.springframework</groupId>
  39 + <artifactId>spring-context</artifactId>
  40 + </dependency>
  41 + <dependency>
  42 + <groupId>org.springframework</groupId>
  43 + <artifactId>spring-context-support</artifactId>
  44 + </dependency>
  45 + <!-- spring相关 end -->
  46 +
  47 + <!-- quartz相关 begin -->
  48 + <dependency>
  49 + <groupId>org.quartz-scheduler</groupId>
  50 + <artifactId>quartz</artifactId>
  51 + </dependency>
  52 + <!-- quartz相关 end -->
  53 +
  54 +
  55 +
  56 + </dependencies>
  57 +
  58 +</project>
0 59 \ No newline at end of file
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/TccCompensableAspect.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/TccCompensableAspect.java
  1 +package org.mengyun.tcctransaction.spring;
  2 +
  3 +import org.aspectj.lang.ProceedingJoinPoint;
  4 +import org.aspectj.lang.annotation.Around;
  5 +import org.aspectj.lang.annotation.Aspect;
  6 +import org.aspectj.lang.annotation.Pointcut;
  7 +import org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.core.Ordered;
  11 +
  12 +/**
  13 + * Created by changmingxie on 10/30/15.
  14 + * TCC补偿切面(切面是通知和切点的结合).
  15 + * 拦截带@Compensable注解的可补偿事务方法.
  16 + */
  17 +@Aspect
  18 +public class TccCompensableAspect implements Ordered {
  19 + /** 日志记录器 */
  20 + private static final Logger LOG = LoggerFactory.getLogger(TccCompensableAspect.class);
  21 +
  22 + /** 优先级顺序(值较低的那个有更高的优先级) */
  23 + // 对于Around增强,方法前增强较低的优先级先执行,方法后的增强较高的优先级先执行
  24 + private int order = Ordered.HIGHEST_PRECEDENCE;
  25 + public void setOrder(int order) {
  26 + this.order = order;
  27 + }
  28 + @Override
  29 + public int getOrder() {
  30 + return 0;
  31 + }
  32 +
  33 + /** 可补偿事务拦截器 */
  34 + private CompensableTransactionInterceptor compensableTransactionInterceptor;
  35 + public void setCompensableTransactionInterceptor(CompensableTransactionInterceptor compensableTransactionInterceptor) {
  36 + this.compensableTransactionInterceptor = compensableTransactionInterceptor;
  37 + }
  38 +
  39 + /**
  40 + * 定义切入点(包含切入点表达式和切点签名,切点用于准确定位应该在什么地方应用切面的通知,切点可以被切面内的所有通知元素引用).
  41 + */
  42 + @Pointcut("@annotation(org.mengyun.tcctransaction.api.annotation.Compensable)")
  43 + public void compensableService() {
  44 +
  45 + }
  46 +
  47 + /**
  48 + * 定义环绕增强(在一个方法执行之前和执行之后运行,第一个参数必须是 ProceedingJoinPoint类型,pjp将包含切点拦截的方法的参数信息)
  49 + * @param pjp
  50 + * @throws Throwable
  51 + */
  52 + @Around("compensableService()")
  53 + public Object interceptCompensableMethod(ProceedingJoinPoint pjp) throws Throwable {
  54 + LOG.debug("==>TccCompensableAspect interceptCompensableMethod");
  55 + return compensableTransactionInterceptor.interceptCompensableMethod(pjp);
  56 + }
  57 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/TccTransactionContextAspect.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/TccTransactionContextAspect.java
  1 +package org.mengyun.tcctransaction.spring;
  2 +
  3 +import org.aspectj.lang.ProceedingJoinPoint;
  4 +import org.aspectj.lang.annotation.Around;
  5 +import org.aspectj.lang.annotation.Aspect;
  6 +import org.aspectj.lang.annotation.Pointcut;
  7 +import org.mengyun.tcctransaction.interceptor.ResourceCoordinatorInterceptor;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.core.Ordered;
  11 +
  12 +/**
  13 + * Created by changmingxie on 11/8/15.
  14 + * TCC事务上下文切面。
  15 + * 拦截带@Compensable注解或包含TransactionContext参数的可补偿事务方法.
  16 + */
  17 +@Aspect
  18 +public class TccTransactionContextAspect implements Ordered {
  19 + /** 日志记录器 */
  20 + private static final Logger LOG = LoggerFactory.getLogger(TccTransactionContextAspect.class);
  21 +
  22 + /** 优先级顺序(值较低的那个有更高的优先级) */
  23 + // 对于Around增强,方法前增强较低的优先级先执行,方法后的增强较高的优先级先执行
  24 + private int order = Ordered.HIGHEST_PRECEDENCE;
  25 + public void setOrder(int order) {
  26 + this.order = order;
  27 + }
  28 + @Override
  29 + public int getOrder() {
  30 + return 0;
  31 + }
  32 +
  33 + /** 资源协调拦截器 */
  34 + private ResourceCoordinatorInterceptor resourceCoordinatorInterceptor;
  35 + public void setResourceCoordinatorInterceptor(ResourceCoordinatorInterceptor resourceCoordinatorInterceptor) {
  36 + this.resourceCoordinatorInterceptor = resourceCoordinatorInterceptor;
  37 + }
  38 +
  39 + /**
  40 + * 定义切入点(包含切入点表达式和切点签名).
  41 + */
  42 + @Pointcut("execution(public * *(org.mengyun.tcctransaction.api.TransactionContext,..))||@annotation(org.mengyun.tcctransaction.api.annotation.Compensable)")
  43 + public void transactionContextCall() {
  44 +
  45 + }
  46 +
  47 + /**
  48 + * 定义环绕增强(在一个方法执行之前和执行之后运行,第一个参数必须是 ProceedingJoinPoint类型,方法的调用者得到的返回值就是环绕通知返回的值)
  49 + * @param pjp
  50 + * @throws Throwable
  51 + */
  52 + @Around("transactionContextCall()")
  53 + public Object interceptTransactionContextMethod(ProceedingJoinPoint pjp) throws Throwable {
  54 + LOG.debug("==>TccTransactionContextAspect interceptTransactionContextMethod(ProceedingJoinPoint pjp)");
  55 + return resourceCoordinatorInterceptor.interceptTransactionContextMethod(pjp);
  56 + }
  57 +
  58 +
  59 +
  60 +
  61 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/recover/DefaultRecoverConfig.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/recover/DefaultRecoverConfig.java
  1 +package org.mengyun.tcctransaction.spring.recover;
  2 +
  3 +import org.mengyun.tcctransaction.recover.RecoverConfig;
  4 +
  5 +/**
  6 + * Created by changming.xie on 6/1/16.
  7 + * 默认事务恢复配置。
  8 + */
  9 +public class DefaultRecoverConfig implements RecoverConfig {
  10 + public static final RecoverConfig INSTANCE = new DefaultRecoverConfig();
  11 +
  12 + /** 一个事务最多尝试恢复次数(超过将不在自动恢复,需要人工干预,默认是30次)*/
  13 + private int maxRetryCount = 30;
  14 +
  15 + /**
  16 + * 一个事务日志当超过一定时间间隔后没有更新就会被认为是发生了异常,需要恢复,
  17 + * 恢复Job将扫描超过这个时间间隔依旧没有更新的事务日志,并对这些事务进行恢复,时间单位是秒,默认是120秒
  18 + */
  19 + private int recoverDuration = 120; //120 seconds
  20 +
  21 + /** 恢复Job触发间隔配置,默认是(每分钟) */
  22 + private String cronExpression = "0 */1 * * * ?";
  23 +
  24 + @Override
  25 + public int getMaxRetryCount() {
  26 + return maxRetryCount;
  27 + }
  28 +
  29 + @Override
  30 + public int getRecoverDuration() {
  31 + return recoverDuration;
  32 + }
  33 +
  34 + @Override
  35 + public String getCronExpression() {
  36 + return cronExpression;
  37 + }
  38 +
  39 + public void setMaxRetryCount(int maxRetryCount) {
  40 + this.maxRetryCount = maxRetryCount;
  41 + }
  42 +
  43 + public void setRecoverDuration(int recoverDuration) {
  44 + this.recoverDuration = recoverDuration;
  45 + }
  46 +
  47 + public void setCronExpression(String cronExpression) {
  48 + this.cronExpression = cronExpression;
  49 + }
  50 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/recover/RecoverScheduledJob.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/recover/RecoverScheduledJob.java
  1 +package org.mengyun.tcctransaction.spring.recover;
  2 +
  3 +import org.mengyun.tcctransaction.exception.SystemException;
  4 +import org.mengyun.tcctransaction.recover.TransactionRecovery;
  5 +import org.mengyun.tcctransaction.support.TransactionConfigurator;
  6 +import org.quartz.Scheduler;
  7 +import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
  8 +import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
  9 +
  10 +/**
  11 + * Created by changming.xie on 6/2/16.
  12 + * 事务恢复定时任务。
  13 + */
  14 +public class RecoverScheduledJob {
  15 +
  16 + /** 事务恢复服务 */
  17 + private TransactionRecovery transactionRecovery;
  18 + public void setTransactionRecovery(TransactionRecovery transactionRecovery) {
  19 + this.transactionRecovery = transactionRecovery;
  20 + }
  21 +
  22 + /** 注入的是TCC事务配置器 */
  23 + private TransactionConfigurator transactionConfigurator;
  24 + public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
  25 + this.transactionConfigurator = transactionConfigurator;
  26 + }
  27 +
  28 + /**
  29 + * 事务恢复任务调度器(这里注入的是org.springframework.scheduling.quartz.SchedulerFactoryBean实例)
  30 + */
  31 + private Scheduler scheduler;
  32 + public Scheduler getScheduler() {
  33 + return scheduler;
  34 + }
  35 + public void setScheduler(Scheduler scheduler) {
  36 + this.scheduler = scheduler;
  37 + }
  38 +
  39 + /**
  40 + * 初始化方法,Spring启动时执行.
  41 + */
  42 + public void init() {
  43 +
  44 + try {
  45 + // MethodInvokingJobDetailFactoryBean 负责生成具体的任务,只需要指定某个对象的某个方法,在触发器触发时,即调用指定对象的指定方法。
  46 + MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
  47 + // 指定该任务对应的调用对象,这个对象所属的类无需实现任何接口
  48 + jobDetail.setTargetObject(transactionRecovery);
  49 + // 指定在targetObject对象中某个的方法(此处调用TransactionRecovery中的startRecover方法)
  50 + jobDetail.setTargetMethod("startRecover");
  51 + // 设置任务名称
  52 + jobDetail.setName("transactionRecoveryJob");
  53 + // 是否允许任务并发执行,类默认是并发执行的,这时候如果不设置“concurrent”为false,很可能带来并发或者死锁的问题,而且几率较小,不容易复现,
  54 + // 设置为false表示等上一个任务执行完后再开启新的任务
  55 + jobDetail.setConcurrent(false);
  56 + jobDetail.afterPropertiesSet();
  57 +
  58 + // 触发器生成器类,用被指定的调度器调度生成指定规则的触发器对象
  59 + // 该类负责在spring容器中创建一个触发器,该类的ID应该在SchedulerFactoryBean属性的List中被引用,这样这个触发器才能保证被某个指定调度器调度
  60 + CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean();
  61 + // 设置触发器名称
  62 + cronTrigger.setBeanName("transactionRecoveryCronTrigger");
  63 + // 触发规则(这里通过事务配置器获取事务恢复定时任务规则)
  64 + System.out.println(transactionConfigurator.getRecoverConfig().getCronExpression());
  65 + cronTrigger.setCronExpression(transactionConfigurator.getRecoverConfig().getCronExpression());
  66 + cronTrigger.setJobDetail(jobDetail.getObject());
  67 + cronTrigger.afterPropertiesSet();
  68 +
  69 + // 设置调度任务
  70 + scheduler.scheduleJob(jobDetail.getObject(), cronTrigger.getObject());
  71 + // 启动任务调度器
  72 + scheduler.start();
  73 +
  74 + } catch (Exception e) {
  75 + e.printStackTrace();
  76 + throw new SystemException(e);
  77 + }
  78 + }
  79 +
  80 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/repository/SpringJdbcTransactionRepository.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/repository/SpringJdbcTransactionRepository.java
  1 +package org.mengyun.tcctransaction.spring.repository;
  2 +
  3 +import org.mengyun.tcctransaction.repository.impl.JdbcTransactionRepository;
  4 +import org.springframework.jdbc.datasource.DataSourceUtils;
  5 +
  6 +import java.sql.Connection;
  7 +
  8 +/**
  9 + * Created by changmingxie on 10/30/15.
  10 + * SpringJdbc事务库。
  11 + */
  12 +public class SpringJdbcTransactionRepository extends JdbcTransactionRepository {
  13 + @Override
  14 + protected Connection getConnection() {
  15 + return DataSourceUtils.getConnection(this.getDataSource());
  16 + }
  17 +
  18 + @Override
  19 + protected void releaseConnection(Connection con) {
  20 + DataSourceUtils.releaseConnection(con, this.getDataSource());
  21 + }
  22 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/support/TccApplicationContext.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/support/TccApplicationContext.java
  1 +package org.mengyun.tcctransaction.spring.support;
  2 +
  3 +import org.mengyun.tcctransaction.support.BeanFactory;
  4 +import org.springframework.beans.BeansException;
  5 +import org.springframework.context.ApplicationContext;
  6 +import org.springframework.context.ApplicationContextAware;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +/**
  10 + * Created by changmingxie on 11/22/15.
  11 + * TCC应用上下文。
  12 + */
  13 +@Component
  14 +public class TccApplicationContext implements BeanFactory, ApplicationContextAware {
  15 +
  16 + private ApplicationContext applicationContext;
  17 +
  18 + @Override
  19 + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  20 + this.applicationContext = applicationContext;
  21 + }
  22 +
  23 + @Override
  24 + public Object getBean(Class<?> aClass) {
  25 + return this.applicationContext.getBean(aClass);
  26 + }
  27 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/support/TccBeanPostProcessor.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/support/TccBeanPostProcessor.java
  1 +package org.mengyun.tcctransaction.spring.support;
  2 +
  3 +import org.mengyun.tcctransaction.support.BeanFactory;
  4 +import org.mengyun.tcctransaction.support.BeanFactoryAdapter;
  5 +import org.springframework.context.ApplicationContext;
  6 +import org.springframework.context.ApplicationListener;
  7 +import org.springframework.context.event.ContextRefreshedEvent;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +/**
  11 + * Created by changmingxie on 11/20/15.
  12 + * TCC Bean后置处理程序。
  13 + */
  14 +@Component
  15 +public class TccBeanPostProcessor implements ApplicationListener<ContextRefreshedEvent> {
  16 +
  17 + /**
  18 + * Spring启动时加载.
  19 + */
  20 + @Override
  21 + public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
  22 + ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
  23 +
  24 + if (applicationContext.getParent() == null) {
  25 +
  26 + BeanFactoryAdapter.setBeanFactory(applicationContext.getBean(BeanFactory.class));
  27 + }
  28 + }
  29 +}
... ...
tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/support/TccTransactionConfigurator.java 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/support/TccTransactionConfigurator.java
  1 +package org.mengyun.tcctransaction.spring.support;
  2 +
  3 +import org.mengyun.tcctransaction.TransactionManager;
  4 +import org.mengyun.tcctransaction.recover.RecoverConfig;
  5 +import org.mengyun.tcctransaction.repository.TransactionRepository;
  6 +import org.mengyun.tcctransaction.spring.recover.DefaultRecoverConfig;
  7 +import org.mengyun.tcctransaction.support.TransactionConfigurator;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +
  10 +import javax.annotation.PostConstruct;
  11 +
  12 +/**
  13 + * Created by changmingxie on 11/11/15.
  14 + * TCC事务配置器。
  15 + */
  16 +public class TccTransactionConfigurator implements TransactionConfigurator {
  17 +
  18 + /** 事务repo */
  19 + @Autowired
  20 + private TransactionRepository transactionRepository;
  21 + @Override
  22 + public TransactionRepository getTransactionRepository() {
  23 + return transactionRepository;
  24 + }
  25 +
  26 + /** 事务恢复配置 */
  27 + @Autowired(required = false)
  28 + private RecoverConfig recoverConfig = DefaultRecoverConfig.INSTANCE;
  29 + @Override
  30 + public RecoverConfig getRecoverConfig() {
  31 + return recoverConfig;
  32 + }
  33 +
  34 + /**
  35 + * 根据事务配置器创建事务管理器.
  36 + */
  37 + private TransactionManager transactionManager = new TransactionManager();
  38 + @Override
  39 + public TransactionManager getTransactionManager() {
  40 + return transactionManager;
  41 + }
  42 +
  43 + @PostConstruct
  44 + public void init() {
  45 + // 属性注入后调用
  46 + // 1、事务repo注入检测
  47 + if (transactionRepository == null) {
  48 + throw new RuntimeException("自项目必须注入TransactionRepository相关实现类,如SpringJdbcTransactionRepository");
  49 + }
  50 + // 2、事务配置器配置事务repo
  51 + transactionManager.setTransactionRepository(transactionRepository);
  52 + }
  53 +
  54 +
  55 +}
... ...
tcc-transaction-spring/src/main/resources/tcc-transaction.xml 0 → 100644
  1 +++ a/tcc-transaction-spring/src/main/resources/tcc-transaction.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<beans xmlns="http://www.springframework.org/schema/beans"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xmlns:context="http://www.springframework.org/schema/context"
  5 + xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
  6 + xsi:schemaLocation="
  7 + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  8 + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  9 + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
  10 + http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
  11 +
  12 + <!-- 开启Spring对@AspectJ风格切面的支持(因为下面用到自定义的TCC补偿切面类) -->
  13 + <!-- @Aspect注解不能被Spring自动识别并注册为Bean,因此要通过xml的bean配置,或通过@Compenent注解标识其为Spring管理Bean -->
  14 + <aop:aspectj-autoproxy/>
  15 +
  16 + <context:component-scan base-package="org.mengyun.tcctransaction.spring"/>
  17 +
  18 + <!-- TCC事务配置器 -->
  19 + <bean id="tccTransactionConfigurator" class="org.mengyun.tcctransaction.spring.support.TccTransactionConfigurator">
  20 + </bean>
  21 +
  22 + <!-- 可补偿事务拦截器 -->
  23 + <bean id="compensableTransactionInterceptor"
  24 + class="org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor">
  25 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  26 + </bean>
  27 + <!-- TCC补偿切面 -->
  28 + <bean id="tccCompensableAspect" class="org.mengyun.tcctransaction.spring.TccCompensableAspect">
  29 + <property name="compensableTransactionInterceptor" ref="compensableTransactionInterceptor"/>
  30 + </bean>
  31 +
  32 + <!-- 资源协调拦截器 -->
  33 + <bean id="resourceCoordinatorInterceptor"
  34 + class="org.mengyun.tcctransaction.interceptor.ResourceCoordinatorInterceptor">
  35 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  36 + </bean>
  37 + <!-- TCC事务上下文切面 -->
  38 + <bean id="transactionContextAspect" class="org.mengyun.tcctransaction.spring.TccTransactionContextAspect">
  39 + <property name="resourceCoordinatorInterceptor" ref="resourceCoordinatorInterceptor"/>
  40 + </bean>
  41 +
  42 + <!-- 启用定时任务注解 -->
  43 + <task:annotation-driven/>
  44 +
  45 + <!-- 事务恢复任务调度器 -->
  46 + <bean id="recoverScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"/>
  47 + <!-- 事务恢复 -->
  48 + <bean id="transactionRecovery" class="org.mengyun.tcctransaction.recover.TransactionRecovery">
  49 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  50 + </bean>
  51 +
  52 + <!-- 事务恢复调度任务,初始化方法:init -->
  53 + <bean id="recoverScheduledJob" class="org.mengyun.tcctransaction.spring.recover.RecoverScheduledJob" init-method="init">
  54 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  55 + <property name="transactionRecovery" ref="transactionRecovery"/>
  56 + <property name="scheduler" ref="recoverScheduler"/>
  57 + </bean>
  58 +
  59 +</beans>
0 60 \ No newline at end of file
... ...
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/TccCompensableAspect.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/TccTransactionContextAspect.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/recover/DefaultRecoverConfig.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/recover/RecoverScheduledJob.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/repository/SpringJdbcTransactionRepository.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/support/TccApplicationContext.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/support/TccBeanPostProcessor.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/org/mengyun/tcctransaction/spring/support/TccTransactionConfigurator.class 0 → 100644
No preview for this file type
tcc-transaction-spring/target/classes/tcc-transaction.xml 0 → 100644
  1 +++ a/tcc-transaction-spring/target/classes/tcc-transaction.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<beans xmlns="http://www.springframework.org/schema/beans"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xmlns:context="http://www.springframework.org/schema/context"
  5 + xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
  6 + xsi:schemaLocation="
  7 + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  8 + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  9 + http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
  10 + http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
  11 +
  12 + <!-- 开启Spring对@AspectJ风格切面的支持(因为下面用到自定义的TCC补偿切面类) -->
  13 + <!-- @Aspect注解不能被Spring自动识别并注册为Bean,因此要通过xml的bean配置,或通过@Compenent注解标识其为Spring管理Bean -->
  14 + <aop:aspectj-autoproxy/>
  15 +
  16 + <context:component-scan base-package="org.mengyun.tcctransaction.spring"/>
  17 +
  18 + <!-- TCC事务配置器 -->
  19 + <bean id="tccTransactionConfigurator" class="org.mengyun.tcctransaction.spring.support.TccTransactionConfigurator">
  20 + </bean>
  21 +
  22 + <!-- 可补偿事务拦截器 -->
  23 + <bean id="compensableTransactionInterceptor"
  24 + class="org.mengyun.tcctransaction.interceptor.CompensableTransactionInterceptor">
  25 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  26 + </bean>
  27 + <!-- TCC补偿切面 -->
  28 + <bean id="tccCompensableAspect" class="org.mengyun.tcctransaction.spring.TccCompensableAspect">
  29 + <property name="compensableTransactionInterceptor" ref="compensableTransactionInterceptor"/>
  30 + </bean>
  31 +
  32 + <!-- 资源协调拦截器 -->
  33 + <bean id="resourceCoordinatorInterceptor"
  34 + class="org.mengyun.tcctransaction.interceptor.ResourceCoordinatorInterceptor">
  35 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  36 + </bean>
  37 + <!-- TCC事务上下文切面 -->
  38 + <bean id="transactionContextAspect" class="org.mengyun.tcctransaction.spring.TccTransactionContextAspect">
  39 + <property name="resourceCoordinatorInterceptor" ref="resourceCoordinatorInterceptor"/>
  40 + </bean>
  41 +
  42 + <!-- 启用定时任务注解 -->
  43 + <task:annotation-driven/>
  44 +
  45 + <!-- 事务恢复任务调度器 -->
  46 + <bean id="recoverScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"/>
  47 + <!-- 事务恢复 -->
  48 + <bean id="transactionRecovery" class="org.mengyun.tcctransaction.recover.TransactionRecovery">
  49 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  50 + </bean>
  51 +
  52 + <!-- 事务恢复调度任务,初始化方法:init -->
  53 + <bean id="recoverScheduledJob" class="org.mengyun.tcctransaction.spring.recover.RecoverScheduledJob" init-method="init">
  54 + <property name="transactionConfigurator" ref="tccTransactionConfigurator"/>
  55 + <property name="transactionRecovery" ref="transactionRecovery"/>
  56 + <property name="scheduler" ref="recoverScheduler"/>
  57 + </bean>
  58 +
  59 +</beans>
0 60 \ No newline at end of file
... ...
tcc-transaction-spring/target/maven-archiver/pom.properties 0 → 100644
  1 +++ a/tcc-transaction-spring/target/maven-archiver/pom.properties
  1 +#Generated by Maven
  2 +#Tue Jan 14 10:24:31 CST 2020
  3 +version=1.1.5_comment
  4 +groupId=org.mengyun
  5 +artifactId=tcc-transaction-spring
... ...
tcc-transaction-spring/target/tcc-transaction-spring-1.1.5_comment-sources.jar 0 → 100644
No preview for this file type
tcc-transaction-spring/target/tcc-transaction-spring-1.1.5_comment.jar 0 → 100644
No preview for this file type