bugfix> java > 投稿

この問題は、スプリング4.1.2から5.0.5、スプリングバッチ3.0.9から4.0.1、および休止状態4.2.0から5.2.16への移行後に開始されました。 次の形式の春バッチタスクレットがあります-

public class MyTasklet implements Tasklet {
                    public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) {
                        a();
                    }
                    public void a(){
                    //a few hibernate calls here
                    }
        }

ここで、hibernateトランザクションの境界をexecute()メソッドではなく、メソッドa()[executeから呼び出される]にする必要があります。 しかし、同じことを達成するためにポイントカットを適用しようとすると、メッセージが表示されます「進行中のトランザクションはありません」。以下のサンプルxmlを提供しました。

aopポイントカット-メソッド名 'a' [i.e public * myPackage.MyTasklet.a(..) の代わりに ]、 * を使用する場合(すなわち、 public * myPackage.MyTasklet.*(..) ]または 'execute' [i.e public * myPackage.MyTasklet.execute(..) ]コードは正常に動作します。技術的な理由により、境界を「a」にすることが重要です。そのため、「実行」または他の方法を境界として使用することはできません。


<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" />
        </tx:attributes>
</tx:advice>
<bean id="transactionManager"
        class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory" />
</bean>
<aop:config>
        <aop:pointcut id="Op1"
            expression="execution(public * myPackage.MyTasklet.a(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="Op1" />
</aop:config>

回答 1 件
  • この質問はここで何百回も質問されています。あなたのメソッド a()  は内部的に呼び出されますが、内部メソッド呼び出しはSpring AOPによってインターセプトされません。その場合、実際には this.a() を呼び出すためです 。これは、Spring AOPが使用するラッピング動的プロキシを通過しません。 a() の場合  外部から呼び出されました別のコンポーネントによって機能します。この動作は、Spring AOPマニュアルに包括的に文書化されています。

    内部メソッド呼び出しをインターセプトする場合は、Spring AOPの代わりにAspectJを使用する必要があります。 SpringをAspectJおよびLTW(ロードタイムウィービング)用に構成する方法も、Springのマニュアルに記載されています。

    追伸:これは、バージョンのアップグレードとはまったく関係ありません。古いSpringおよびSpring Batchバージョンでは同じです。混ぜたリファクタリング (バージョンアップグレード)と機能変更、これは絶対にしないでください。デバッグ用の移動ターゲットが多すぎます。リファクタリングとは、機能を変更せずにコード(または、この場合は構成)を変更することです。

あなたの答え