Commit 8835836f4e71205b2015905e4d6d074f20f266f1
0 parents
tcc-transaction-1.1.5 注释版,版权是原作者的
Showing
99 changed files
with
3293 additions
and
0 deletions
.gitignore
0 → 100644
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
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
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
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
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