このプロジェクトはすでに1.0で開始されており、全体的な反応は非常に良好です。少し面倒な人は毎日30〜50を稼ぐことができ、上手くいく人は1日50〜100以上を稼ぐことができます。
このプロジェクトは非常にシンプルです。私たちが行っているのは、トラフィック所有者の広告収入です。1,000程度の読み取りで、他のセルフメディアプラットフォームの広告収入よりもはるかに高い10〜20以上の収入を得ることができます。完全に受動的な収入と言え、記事を投稿するのに毎日30分もかからない!
こんにちは、みなさん、みなさん、今日は春の枠組み問題の原則を説明します。
Springトランザクションには、構成ファイルとアノテーションの2つの方法があります。ここでは、構成ファイルの方法の原則については紹介しません。今回は、アノテーション@Transactionalの原則の説明に焦点を当てます。
1つ:アノテーション@Transactional実装の原則プロセス:
1。サーバーの起動時にアノテーションスキャンが実行され、@ Transactionalを持つすべてのメソッドがaopプロキシオブジェクトに生成されます
。2。呼び出し元がメソッドを呼び出すと、aopにカットされます。実際のaopのプロキシオブジェクトが呼び出されます。3。jdbc
トランザクションがaopプロキシオブジェクトで開かれ、実際のメソッドが呼び出されます
。4。aopプロキシオブジェクトは、メソッドの実行時にコミットまたはロールバックします。
2:例外がスローされた後、トランザクションのロールバックが失敗するのはなぜですか?
場合によっては、例外が発生してスローされましたが、ロールバックが失敗しました。何が起こっているのでしょうか。この問題を理解するには、Springトランザクションのソースコードを詳細に解釈する必要があります。主要なコアソースコードはorg.springframeworkにあります。 .transaction.interceptor.TransactionAspectSupport、メソッドinvokeWithinTransactionはトランザクションのロジックを制御し、ソースコードは次のとおりです。
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
final TransactionAttribute txAttr = this.getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = this.determineTransactionManager(txAttr);
final String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
Object result;
if (txAttr != null && tm instanceof CallbackPreferringPlatformTransactionManager) {
final TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder();
try {
result = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus status) {
TransactionAspectSupport.TransactionInfo txInfo = TransactionAspectSupport.this.prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
Object var4;
try {
Object var3 = invocation.proceedWithInvocation();
return var3;
} catch (Throwable var8) {
if (txAttr.rollbackOn(var8)) {
if (var8 instanceof RuntimeException) {
throw (RuntimeException)var8;
}
throw new TransactionAspectSupport.ThrowableHolderException(var8);
}
throwableHolder.throwable = var8;
var4 = null;
} finally {
TransactionAspectSupport.this.cleanupTransactionInfo(txInfo);
}
return var4;
}
});
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
} else {
return result;
}
} catch (TransactionAspectSupport.ThrowableHolderException var18) {
throw var18.getCause();
} catch (TransactionSystemException var19) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
var19.initApplicationException(throwableHolder.throwable);
}
throw var19;
} catch (Throwable var20) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw var20;
}
} else {
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
try {
//1.执行调用链,循环调用执行前置方法,真实方法
result = invocation.proceedWithInvocation();
} catch (Throwable var16) {
//1.2出现异常后,进行处理,回滚事务
this.completeTransactionAfterThrowing(txInfo, var16);
throw var16;
} finally {
this.cleanupTransactionInfo(txInfo);
}
//2.方法执行顺利,调用后置方法,提交事务
this.commitTransactionAfterReturning(txInfo);
return result;
}
}
コードの最も重要な行についてコメントしました。全体的なロジックは、最初に実際のメソッドのフロントエンドの側面を実行してから、実際のメソッドを実行することです。例外がある場合は、処理され(トランザクションのロールバック)、例外がない場合は、トランザクションが送信され、拡張後のメソッドが実装されます。
したがって、トランザクションのロールバックが失敗する理由を理解するには、メソッドthis.completeTransactionAfterThrowing(txInfo、var16)をさらに詳しく調べる必要があります。ソースコードは次のとおりです。
protected void completeTransactionAfterThrowing(TransactionAspectSupport.TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.hasTransaction()) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
}
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
} catch (TransactionSystemException var7) {
this.logger.error("Application exception overridden by rollback exception", ex);
var7.initApplicationException(ex);
throw var7;
} catch (RuntimeException var8) {
this.logger.error("Application exception overridden by rollback exception", ex);
throw var8;
} catch (Error var9) {
this.logger.error("Application exception overridden by rollback error", ex);
throw var9;
}
} else {
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
} catch (TransactionSystemException var4) {
this.logger.error("Application exception overridden by commit exception", ex);
var4.initApplicationException(ex);
throw var4;
} catch (RuntimeException var5) {
this.logger.error("Application exception overridden by commit exception", ex);
throw var5;
} catch (Error var6) {
this.logger.error("Application exception overridden by commit error", ex);
throw var6;
}
}
}
}
ソースコードから、処理されるのはランタイムRuntimeExceptionおよびその他の例外であることがわかります。このため、Springは、スローされたときに一部の非ランタイム例外を処理しなかったため、ロールバックはありませんでした。
異常な統合関係図は次のとおりです。
上の図から、IOと同様に、SQL例外が特定の処理を受けない場合、SQL例外はロールバックされないことがわかります。
ソースコードには、トランザクション実行時のトランザクションステータスに基づく詳細コードtxInfo.getTransactionStatus()の行もあります。これが、トランザクションを手動でロールバックするためのコードが次のように記述されている理由です。
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
ソースコードをクリックすると、トランザクションステータスがデフォルトでfalse(コミット済みを意味する)であることがわかります。このメソッドを呼び出すと、true(ロールバック)に変更されます。
public abstract class AbstractTransactionStatus implements TransactionStatus {
private boolean rollbackOnly = false;
private boolean completed = false;
private Object savepoint;
public AbstractTransactionStatus() {
}
public void setRollbackOnly() {
this.rollbackOnly = true;
}
………………
したがって、要約すると、スプリングトランザクションのロールバックには2つの理由があり
ます。1。スローされた例外は非ランタイム例外RuntimeExceptionです
。2。トランザクションステータスは人為的に変更されます。
では、この問題を解決する方法はありますか?
もちろん、それが人為的なものである場合は、調整または削除する対応するコードを見つけるだけで済みます。
それが動作しない例外である場合、Springもこの問題の解決策を作成しました。2つのオプションがあります
。1。ロールバックを構成します。
@ Transactional(rollbackFor = Exception.class)
2。トランザクションを手動でロールバックします。
例外を取得した後、位置コードを呼び出します。TransactionAspectSupport.currentTransactionStatus()。setRollbackOnly();最後に、例外をスローします。
rollbackForは、実行時以外の例外をキャプチャしてロールバックするようにSpringFrameworkに指示します。= Exception.classは、キャプチャするSpringFrameworkのスコープを指示します。したがって、例外をカスタマイズして、ロールバック用に特定の例外のみを取得することもできます。