Spring5 AOPはデフォルトでCglibを使用しますか?この声明を初めて聞いたのはWeChatグループでした。
グループチャット
本物か偽物か?ドキュメントを見る
この声明を最初に見たとき、私は懐疑的でした。
Spring5より前のバージョンのAOPがデフォルトでJDK動的プロキシを使用していることは誰もが知っていますが、Spring5のバージョンが変更されているというのは本当ですか?そこで、Spring Framework 5.xドキュメントを開いて、もう一度確認しました。
ドキュメントアドレス:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/core.html#aop
Spring Framework5.xのドキュメント
単に翻訳してください。Spring AOPは、デフォルトでJDK動的プロキシを使用します。オブジェクトがインターフェイスを実装していない場合は、CGLIBプロキシを使用します。もちろん、CGLIBプロキシの使用を強制することもできます。
何?間違った文書?!
公式文書をグループに送った後、このクラスメートから次のような返信がありました。
間違った文書?!
SpringBoot2.xのコード例
文書が間違っていたことを証明するために、学生はデモも書きました。それでは、デモプログラムを再現しましょう。
動作環境:SpringBoot 2.2.0.RELEASEバージョン、組み込みのSpringFrameworkバージョンは5.2.0.RELEASEバージョンです。同時に、spring-boot-starter-aop依存関係を追加して、SpringAOPを自動的にアセンブルします。
public interface UserService {
void work();
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void work() {
System.out.println("开始干活...coding...");
}
}
@Component
@Aspect
public class UserServiceAspect {
@Before("execution(* com.me.aop.UserService.work(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("UserServiceAspect.....()");
}
}
Cglibプロキシはデフォルトで使用されますか?
UserServiceImpl
UserService
インターフェースである実装、及び方法は、事前拡張傍受するために使用されます。UserServiceAspect
UserService#work
実行結果から判断すると、ここではJDK動的プロキシの代わりにCGLIBプロキシが実際に使用されています。
ドキュメントは本当に間違っていますか?!
@EnableAspectJAutoProxyソースコード注釈
Spring Frameworkでは、@EnableAspectJAutoProxy
注釈を使用してSpringAOP関連の機能を有効にします。
Spring Framework5.2.0.RELEASEバージョンの@EnableAspectJAutoProxy
注釈のソースコードは次のとおりです。
@EnableAspectJAutoProxyソースコード
ソースコードのコメントから、次のことがわかります。SpringFramework 5.2.0.RELEASEバージョンでproxyTargetClass
は、デフォルト値がfalse
デフォルトのままであるか、JDK動的プロキシがデフォルトで使用されます。
ドキュメントとソースコードのコメントは間違っていますか?!
@EnableAspectJAutoProxyのproxyTargetClassが無効ですか?
次に、@EnableAspectJAutoProxy
JDK動的プロキシの使用を強制しようとしました。
動作環境:SpringBoot 2.2.0.RELEASEバージョン、組み込みのSpringFrameworkバージョンは5.2.0.RELEASEバージョンです。
proxyTargetClassの設定が無効ですか?
実行中に、CGLIBプロキシがまだ使用されていることがわかりました。ある設定無効は?@EnableAspectJAutoProxy
proxyTargetClass
Spring Framework 5.x
アイデアを整理する
-
Spring5はAOPを開始し、デフォルトでCGLIBを使用すると言う人もいます。
-
Spring Framework 5.xのドキュメントと
@EnableAspectJAutoProxy
ソースコードのコメントはすべて、デフォルトではJDK動的プロキシを使用することであると述べています -
プログラムの操作結果は、インターフェースが継承され
proxyTargetClass
てfalse
に設定されている場合でも、プログラムはCGLIBプロキシを使用していることを示しています。
ちょっと待ってください、何か足りないのですか?
サンプルプログラムはSpringBootを使用して実行されます。SpringBootを使用せず、SpringFrameworkのみを使用する場合はどうなりますか?
動作環境:Spring Framework5.2.0.RELEASEバージョン。UserServiceImplクラスとUserServiceAspectクラスは上記と同じなので、ここでは繰り返しません。
Spring Framework 5.x Spring Framework 5.xLingageCGLIB
実行結果は次のことを示しています。SpringFramework5.xバージョンでは、クラスがインターフェイスを実装している場合、AOPはデフォルトでJDK動的プロキシを使用します。
アイデアを再編成する
-
Spring5 AOPは引き続きデフォルトでJDK動的プロキシを使用しており、公式ドキュメントとソースコードのコメントは正しいです。
-
SpringBoot 2.xバージョンでは、AOPはデフォルトでcglibを使用し、
proxyTargetClass
変更できません。 -
SpringBoot 2.xはいくつかの変更を加えましたか?
SpringBoot2.xに再度アクセスします
上記の分析の結果、Spring Boot2.xバージョンがSpringAOPの関連する構成を変更した可能性が非常に高いです。次に、ソースコード分析の波を見て、内部で何が行われたかを確認しましょう。
ソースコード分析
ソースコード分析、適切なエントリを見つけることは非常に重要です。今回の入り口はどこですか?
@SpringBootApplication
@EnableAutoConfiguration
多数の自動組立を実現するために使用される複合注釈です。
EnableAutoConfiguration
これは、注釈にマークされている結合注釈でもあり@Import
ます。@Import
詳細な使用の注釈、著者の以前の記事を参照してください。https://mp.weixin.qq.com/s/7arh4sVH1mlHE0GVVbZ84Q
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
AutoConfigurationImportSelector
DeferredImportSelector
インターフェイスが実装されています。
Spring Framework 4.xバージョンでは、これは空のインターフェイスであり、ImportSelector
インターフェイスを継承するだけです。5.xバージョンでは、DeferredImportSelector
インターフェイスが拡張され、getImportGroup
メソッドが追加されました。
AutoConfigurationImportSelector#getImportGroup
AutoConfigurationGroup
クラスはこのメソッドで返されます。これはAutoConfigurationImportSelector
、DeferredImportSelector.Group
インターフェイスを実装する内部クラスです。
SpringBoot 2.xバージョンでは、AutoConfigurationImportSelector.AutoConfigurationGroup#process
自動構成クラスはメソッドを介してインポートされます。
構成クラスのインポート
ブレークポイントのデバッグを通じて、AOPに関連する自動構成がによって構成されていることがわかりorg.springframework.boot.autoconfigure.aop.AopAutoConfiguration
ます。
AopAutoConfigurationソースコード
真実が明らかにされる
これを見て、真実が明らかにされたと言えます。SpringBoot 2.xバージョンでAopAutoConfiguration
は、AOPはにまで自動的にアセンブルされます。
デフォルトでは、spring.aop.proxy-target-class
そのような構成アイテムは絶対にありません。現時点では、SpringBoot2.xではCglibがデフォルトで使用されます。
SpringBoot2.xでAOP実装を変更する方法
ソースコードを通じて、SpringBoot 2.xでAOPの実装を変更する必要がある場合は、spring.aop.proxy-target-class
この構成アイテムを介して変更する必要があることもわかります。
#在application.properties文件中通过spring.aop.proxy-target-class来配置
spring.aop.proxy-target-class=false
spring-configuration-metadata.json
spring-configuration-metadata.json
ファイルの役割についても説明します。application.properties
またはapplication.yml
ファイルを使用する場合、IDEAはこれらのファイル情報を読み取ることでコードヒントを提供し、SpringBootフレームワーク自体はこの構成ファイルを読み取りません。
SringBoot1.5.xはどうですか
SringBoot 1.5.x
ご覧のとおり、SpringBoot 1.5.xでは、JDK動的プロキシがデフォルトで引き続き使用されます。
SpringBoot2.xがデフォルトでCglibを使用する理由
SpringBoot 2.xがデフォルトでCglibを使用してAOPを実装するのはなぜですか?これを行うことの利点は何ですか?著者はインターネットからいくつかの情報を見つけました。最初に問題を見てみましょう。
Spring Bootの問題#5423
@EnableTransactionManagement(proxyTargetClass = true)#5423を使用します
https://github.com/spring-projects/spring-boot/issues/5423
この号では、次のような問題が発生しました。
image.png
翻訳:人々がインターフェースを使用しないときに迷惑なプロキシの問題を防ぐために、@ EnableTransactionManagement(proxyTargetClass = true)を使用する必要があります。
この「インターフェースを使用しないときの厄介なプロキシの問題」とは何ですか?ちょっと考えてみてください。
迷惑な代理店の問題
現時点で使用する必要のあるUserServiceImpl
sumUserService
クラスがあるとします。Springでは、通常、次のようなコードを記述するために使用されます。UserContoller
UserService
@Autowired
UserService userService;
この場合、JDKダイナミックプロキシとCGLIBのどちらを使用していても問題ありません。
しかし、コードが次のような場合はどうなりますか?
@Autowired
UserServiceImpl userService;
現時点で、JDK動的プロキシを使用している場合、起動時にエラーが報告されます。
起動エラー
JDK動的プロキシはインターフェイスベースであるため、プロキシによって生成されたオブジェクトは、インターフェイス変数にのみ割り当てることができます。
そして、CGLIBにはこの問題はありません。CGLIBはサブクラスを生成することによって実装されるため、プロキシオブジェクトがインターフェイスに割り当てられているか実装クラスに割り当てられているかに関係なく、どちらもプロキシオブジェクトの親クラスです。
SpringBootは正確にこの考慮事項から外れているため、バージョン2.xでは、AOPのデフォルトの実装がCGLIBに変更されました。
より詳細な情報については、読者は自分で上記の問題を参照することができます。
総括する
-
Spring 5.xでも、AOPはデフォルトでJDK動的プロキシを使用します。
-
SpringBoot 2.x以降、JDK動的プロキシの使用によって発生する可能性のある型変換例外を解決するために、デフォルトでCGLIBが使用されます。
-
SpringBoot 2.xでは、デフォルトでJDK動的プロキシを使用する必要がある場合、構成アイテムを使用して
spring.aop.proxy-target-class=false
変更でき、proxyTargetClass
構成は無効です。
参考文献
問題:デフォルトのCGLibプロキシ設定のデフォルトは、コアフレームワークアノテーション(@ EnableTransactionManagement、@ EnableAspectJAutoProxy)を使用してオーバーライドできません#12194
https://github.com/spring-projects/spring-boot/issues/12194
この問題proxyTargetClass
は@EnableAspectJAutoProxy
、議論の失敗を設定する問題についても話します:、、@EnableCaching
および @EnableTransactionManagement
。興味のある読者は自分で問題を調べることができます。
オリジナル:https://javazhiyin.blog.csdn.net/article/details/103296297
●なぜアリババは90秒で100億に抵抗できるのですか?-サーバー側の高同時分散アーキテクチャの進化
● B2Beコマースプラットフォーム--ChinaPayUnionPay電子決済機能
● Zookeeperの分散ロックを学び、インタビュアーに感心してあなたを見てもらいましょう
● SpringCloudeコマーススパイクマイクロサービス-Redisson分散ロックソリューション
もっと良い記事をチェックして、公式アカウントを入力してください-私にお願いします-過去に素晴らしい
深くソウルフルなパブリックアカウント0.0