春の裏偎

春のHabrは開いおいるようです。 「Why I Hate Spring」ずいう蚘事の翻蚳者ずコメンテヌタヌに感謝したす。タむトルの匷い吊定的なメッセヌゞにもかかわらず、倚くの興味深い議論を匕き起こしたした。たた、私の最埌の蚘事2017幎のSpringの曞き方に答えおくれたした 。 前回の蚘事ぞのコメントのおかげで、この蚘事が登堎したした。







今回は、Springフレヌムワヌクの深intoに飛び蟌み、その魔法を公開し、基本的なWebアプリケヌションが内郚からどのように芋えるかを確認し、どのようなタスクずSpring Bootがそれを解決するかを理解したす。







前の蚘事ぞのコメントで、䜕人かの人々は、春のHello Worldの䟋はただあたり瀺唆的ではないず指摘したした。 Springは、特にSpring Bootを䜿甚するず、シンプルさず党胜の感芚を䞎えたすが、フレヌムワヌクの基本ず内臓を理解しおいないず、ログのスタックトレヌスを取埗する倧きな危険に぀ながりたす。 さお、䜕が起きおいるのかずいう完党な魔法の感芚を少しでも払拭するために、今日はアプリケヌションを前の蚘事から取り䞊げ、フレヌムワヌク内でどのように䜕が起こっおいるのか、ブヌトがブロックしおいる問題を分析したす。 察象読者はただ初心者の開発者ですが、JavaずSpringの経隓ず基本的な知識がありたす。 ただし、経隓豊富なSpringナヌザヌにずっおは、内郚で䜕が起きおいるかに぀いおの知識を曎新するこずは興味深いかもしれたせん。







キヌコンセプト



ビン



Springの最も基本的な抂念でカバヌを砎り始めたしょう。 Beanは、最も䞀般的なオブゞェクトにすぎたせん。 唯䞀の違いは、Springによっお管理され、DIコンテナ内に存圚するオブゞェクトをBeanで呌び出すのが䞀般的であるこずです。 SpringのほずんどすべおはBeanです-サヌビス、コントロヌラヌ、リポゞトリヌ。実際、アプリケヌション党䜓はBeanのセットで構成されおいたす。 それらは、登録、䟝存関係ずしお受信、プロキシ、びしょ濡れなどにできたす。







DIコンテナ



Springの重芁か぀基本的なメカニズム。 倖芳は非垞にシンプルですが、内郚には䟝存関係を埮調敎するための倚くのメカニズムが甚意されおいたす。 基本的に、Springアプリケヌションは、DIコンテナを介しお接続されたBeanのコレクションです。







倚くの堎合、Springに぀いお議論するずき、軜量のDIコンテナGuiceなどに簡単に眮き換えるこずができ、同じようになりたすが、より簡単でシンプルになるずいう議論がありたす。 そしお、ここで理解するこずは非垞に重芁です-Spring DIの䟡倀は、その可甚性の事実ではなく、その基本的な性質にありたす。 実際、Spring゚コシステムのすべおのラむブラリは、このコンテナSpring自䜓を含むにBeanを登録するだけです。䟝存関係の泚入を通じお、アプリケヌション開発者は必芁なコンポヌネントを取埗できたす。 簡単な䟋 Spring Security OAuthを䜿甚する堎合、 application.properties



でOAuthパラメヌタヌを構成application.properties



ず、Spring SecurityはOAuth2RestTemplate



を提䟛したす。これをコヌドに挿入するだけです。 倖郚APIを呌び出すず、このBeanはOAuthトヌクンを取埗する堎所ず方法、曎新する方法、リク゚ストに远加する堎所などを認識したす。 したがっお、ここでのDIの䟡倀は、それが私たちのコヌドずSpring Securityの間の単なる通信メカニズムであるずいうこずです。 たた、DI実装をGuiceに眮き換えるだけでは、Spring Securityがそれを䜿甚し始めるこずもありたせん。 たた、この新しいDIですべおのSpringラむブラリず統合されおいない堎合、その䟡倀は倧幅に䜎䞋したす。







DIコンテナに぀いお議論するずきに倚くの人が芋逃すもう1぀の非垞に重芁な点は、䟝存性泚入を䜿甚しおも、 各コンポヌネントのむンタヌフェむスを䜜成するこずを意味しないこずです。 これは非垞に単玔なアむデアですが、その単玔さのために、必ずしも明癜ではないこずを䜕床も芋おきたした。 さらに、むンタヌフェヌスが1぀しか実装されおいない堎合、むンタヌフェヌスを䜜成するこずは悪い習慣ず芋なされたす。 すなわち クラス自䜓はDIオブゞェクトである可胜性がありたす。 さらに、むンタヌフェヌスがなくおも、テストで濡れるのを防ぐこずはできたせん。 たずえば、Mockitoは、りェットクラスを取埗する方法を知っおいたす。







コンテキスト



ApplicationContext



むンタヌフェむスによっお提瀺されたす。 実際、Springアプリケヌションそのものです。 コンテキストは、アプリケヌション内で発生するさたざたなむベントに応答しお、Beanのラむフサむクルを制埡する機胜も提䟛したすたずえば、シングルトンずしお䜜成するか、リク゚ストごずに䜜成したす。







構成



そのため、アプリケヌションがBeanのセットである堎合、それを機胜させるには、このセットを蚘述する必芁がありたす。







構成は、䜿甚可胜なBeanの単なる説明です。 Springは、アプリケヌションを圢成するBeanのセットを蚘述するためのいく぀かのオプションを提䟛したす。 履歎オプションは、䞀連のxmlファむルを䜿甚したす 。 最近では、 Javaアノテヌションがそれに取っお代わりたした。 Spring Bootは泚釈に基づいお構築されおおり、原則ずしお、ほずんどの最新のラむブラリは泚釈を䜿甚しお構成するこずもできたす。 第3䞖代では、 Bean構成は機胜的なBean登録アプロヌチになりたした。これは、近々登堎するSpring 5の重芁な新機胜の1぀です。







兞型的な構成クラスは次のようになりたす。







 @Configuration class PaymentsServiceConfiguration { @Bean public PaymentProvider paymentProvider() { return new PayPalPaymentProvider(); } @Bean public PaymentService paymentService(PaymentProvider paymentProvider) { return new PaymentService(paymentProvider); } }
      
      





この構成は2぀のビンを定矩し、2番目のビンは最初のビンに䟝存したす。 そしおここで、SpringがPaymentProvider



たすPaymentProvider



むンスタンスを芁求するず、Springはコンテキスト内でそれを芋぀けお提䟛したす。







蚭定は1぀の巚倧なファむルで蚘述する必芁はありたせん。耇数のファむルに分割し、 @Import



アノテヌションを䜿甚しおそれらを結合できたす。







コンポヌネントスキャン



Spring Frameworkのかなり重芁なコンポヌネントであり、アプリケヌション構成を簡玠化するもう1぀のアプロヌチです。 アむデアは非垞にシンプルですMyCoolComponent



クラスがMyCoolComponent



ずいう名前のBeanを登録する必芁があるこずがわかっおいる堎合、毎回@Bean MyCoolComponent myCoolComponent(dependencies...) { return new MyCoolComponent(dependencies...); }



@Bean MyCoolComponent myCoolComponent(dependencies...) { return new MyCoolComponent(dependencies...); }



 目的のクラスに基づいお、Springに自動的に登録しおビンを䜜成させないのはなぜですか このタスクは、コンポヌネントをスキャンするこずで解決されたす。 すなわち クラスを次のように宣蚀するず







 @Component class MyCoolComponent { MyCoolComponent(dependencies...) { } }
      
      





コンポヌネントスキャンを有効にしたすmyCoolComponent



は、クラスコンストラクタヌずすべおの䟝存関係を䜿甚しお、 myCoolComponent



ずいう名前のBeanを䜜成および登録したす。







コンポヌネントのスキャンには泚意する必芁がありたす。 実際、アプリケヌションのコンテキストを暗黙的に倉曎したす。 たずえば、むンタヌフェむスず2぀の実装があり、それぞれに@Component



が指定されおいる堎合、むンタヌフェむスに䟝存関係を挿入しようずするず、Springは芁求を満たす2぀のBeanがあるずいう䟋倖をスロヌしたす。


たずめ



芚えおおくべきこず ApplicationContext



むンタヌフェヌスによっお蚘述されるSpringアプリケヌションは、DIコンテナヌによっお管理されるオブゞェクト Bean のコレクションです。 Beanのセットは、構成クラス @Configuration



アノテヌションを䜿甚しお構成され、むンポヌト @Import



アノテヌションを䜿甚しお結合できたす。







春のブヌツ



次の郚分に進みたす。 MySQLデヌタベヌスぞの接続を蚭定する必芁があるずしたす。 Hibernateで Spring Data JPAをプロバむダヌずしお䜿甚する堎合は、いく぀かのBeanを構成する必芁がありたすEntityManagerFactory



メむンJPAクラス、JDBCドラむバヌを介しおデヌタベヌスに盎接接続するためのDataSource



など しかし、䞀方で、毎回実行し、実際には同じこずを実行する堎合、自動化しないのはなぜですか デヌタベヌスぞの接続文字列を指定し、MySQLドラむバヌぞの䟝存関係を远加した堎合、MySQLを操䜜するために必芁なすべおのBeanを自動的に䜜成しおみたせんか これがSpring Bootの機胜です。 基本的に、 Spring Bootは、コンテキストで必芁なBeanを䜜成する構成クラスの単なるコレクションです。 同様に、手で䜜成するこずもできたす。Bootがこれを自動化したす。







自動蚭定



Spring Bootの重芁な抂念は自動構成です。 基本的に、アプリケヌション内の特定のBeanを䜜成および登録する構成クラスのセットにすぎたせん。 抂しお 、 Embedded Servlet Container自䜓でさえ、蚭定可胜な別のBeanにすぎたせん 自動構成に぀いお知っおおく必芁があるいく぀かの重芁なポむント









Beanを登録するための甚語ず手順



Beanを登録するためのロゞックは、 @ConditionalOn*



アノテヌションのセットによっお制埡されたす。 クラスパス @ConditionalOnClass



にクラスがある堎合、既存のBean @ConditionalOnBean



、Beanが@ConditionalOnMissingBean



 @ConditionalOnMissingBean



などにBeanが䜜成されるように指定できたす。







Spring Bootはこれらのアノテヌションを積極的に䜿甚しお、できるだけ目立たないようにし、ナヌザヌ蚭定ず重ならないようにしたす。







Hello Worldに飛び蟌む



基本的な理論的知識が揃ったので、アプリケヌションの起動時に䜕が起こるかを分析したす。







したがっお、アプリケヌションには次のコヌドが含たれたす。







 @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
      
      





ここで䜕が起こるかを段階的に芋おみたしょう。







クラスDemoApplication





このクラスには、 メタ泚釈である@SpringBootApplication



泚釈 、぀たり 基本的に、いく぀かの泚釈の゚むリアス









すなわち @SpringBootApplication



の存圚には、コンポヌネントスキャン、自動構成が含たれ、これがSpring BootアプリケヌションであるこずをさたざたなSpringコンポヌネント統合テストなどに瀺したす







SpringApplication.run



提䟛されおいる構成のリストおよびDemoApplication



クラス自䜓は構成です。䞊蚘を参照を䜿甚しお、 ApplicationContext



䜜成し、構成し、コン゜ヌルにバナヌを衚瀺し、アプリケヌションの開始時間を远跡したす。 手動のコンテキスト䜜成で眮き換えるこずができたす new AnnotationConfigApplicationContext(DemoApplication.class)



。 名前が瀺すように、これは泚釈を䜿甚しお蚭定されるアプリケヌションコンテキストです。 ただし、このコンテキストは埋め蟌みサヌブレットコンテナに぀いおは䜕も知りたせんし、それ自䜓の実行方法も確かに知りたせん。 圌の盞続人、すでにSpring BootからAnnotationConfigEmbeddedWebApplicationContext



はこれを行うこずができたす、そしお単にmain



メ゜ッドで曞く堎合







 @SpringBootApplication public class DemoApplication { public static void main(String[] args) throws InterruptedException { ApplicationContext applicationContext = new AnnotationConfigEmbeddedWebApplicationContext(DemoApplication.class); } }
      
      





次に、たったく同じ動䜜するアプリケヌションを取埗したす。 AnnotationConfigEmbeddedWebApplicationContext



クラスは、コンテキストでEmbeddedServletContainerFactory



型のBeanを芋぀け、それを介しお組み蟌みコンテナを䜜成および起動したす。 これらはすべお、共通のDIコンテナのフレヌムワヌク内で機胜するこずに泚意しおください。぀たり、このクラスは自分で実装できたす。







@EnableAutoConfiguration



この泚釈には自動構成が含たれたす。 そしお、おそらくここが、春の魔法を暎く重芁なポむントです。 このアノテヌションの宣蚀方法は次のずおりです。







 ... @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { ... }
      
      





すなわち これは、䞊で説明した最も䞀般的な構成むンポヌトです。 EnableAutoConfigurationImportSelector



およびSpring Boot 1.5+の埌続バヌゞョンAutoConfigurationImportSelector



は、コンテキストにいく぀かのビンを远加する単なる構成です。 ただし、このクラスには埮劙な点が1぀ありたす。Bean自䜓を宣蚀するのではなく、いわゆるfactoriesを䜿甚したす。







EnableAutoConfigurationImportSelector



クラスは、 spring.factories



ファむルをspring.factories



、そこからSpring Bootがむンポヌトする自動構成クラスの名前である倀のリストをロヌドしたす。







spring.factories



ファむル spring-boot-autoconfigure.<version>.jar



内のMETA-INF



フォルダヌにありたすは次のずおりです。







 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ ... (100 lines) org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
      
      





すなわち @EnableAutoConfiguration



泚釈は、リストされおいるすべおの構成をむンポヌトしお、目的のBeanをアプリケヌションコンテキストに提䟛したす。







実際、必芁な構成の手動むンポヌトで眮き換えるこずができたす。







 @Import({ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration.class, org.springframework.boot.autoconfigure.aop.AopAutoConfiguration.class, ...}) public class DemoApplication { ... }
      
      





ただし、Spring Bootはすべおの構成を適甚しようずしたすそしおそれらの構成は玄100個ありたす。 気配りのある読者には、明確にする必芁のある質問がすでにいく぀かあるず思いたす。









簡単な芁玄



Spring Bootの「魔法」の䞭心には魔法のようなものはありたせん; Spring Frameworkの完党に基本的な抂念を䜿甚しおいたす。 ぀たり、プロセスは次のように説明できたす。







  1. @SpringBootApplication



    は、 @EnableAutoConfiguration



    アノテヌションを介したコンポヌネントのスキャンず自動構成が含たれたす
  2. @EnableAutoConfiguration



    はEnableAutoConfigurationImportSelector



    クラスをむンポヌトしたす
  3. EnableAutoConfigurationImportSelector



    は、 META-INF/spring.factories



    から構成のリストをロヌドしMETA-INF/spring.factories



  4. 各構成は、必芁なBeanを登録し、さたざたな条件ビンの有無/蚭定、クラスなどを䜿甚しお、アプリケヌションのさたざたな偎面Web、JPA、AMQPなどを構成しようずしたす。
  5. 結果のAnnotationConfigEmbeddedWebApplicationContext



    は、同じDIコンテナ内のファクトリを探しお、埋め蟌みサヌブレットコンテナを実行したす。
  6. サヌブレットコンテナが起動し、アプリケヌションの準備が敎いたした


耇雑に芋えるかもしれたせんが、ほずんどの堎合、アプリケヌション開発者は、ラむブラリの自動構成のサポヌトに぀いお話しおいるのでなければ、自動構成の内郚に入る必芁はありたせん。







蚺断



自動構成レポヌト



䜕か問題が発生した堎合、Spring Bootでは自動構成蚺断を実行し、䜜成されたBeanを確認できたす。 この情報を衚瀺するには、アプリケヌションを--debug



スむッチで実行する必芁がありたす。







 java -jar my-app.jar --debug
      
      





これに応じお、Springは詳现な自動構成レポヌトを発行したす 。







 ========================= AUTO-CONFIGURATION REPORT ========================= Positive matches: ----------------- DataSourceAutoConfiguration matched: - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) DataSourceAutoConfiguration#dataSourceInitializer matched: - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer; SearchStrategy: all) did not find any beans (OnBeanCondition) ... Negative matches: ----------------- ActiveMQAutoConfiguration: Did not match: - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition) ...
      
      





ポゞティブ/ネガティブマッチの行は、 適甚された各自動構成に察応したす 。さらに、ブヌトは特定のビンが䜜成された理由を瀺したす぀たり、どの登録条件が満たされたかを瀺したす。







アクチュ゚ヌタ



Spring Boot Actuatorは、実行䞭のアプリケヌション甚の匷力な蚺断ツヌルであり、倚くの有甚な分析を提䟛できたすさらに、これらのメトリックのセットはアプリケヌションから簡単に拡匵できたす。







Actuatorをプロゞェクトに远加した埌、 Spring BootはURL http://localhost:8080/beans



介しお利甚可胜なBeanのリストを公開したす。 このリストはJMXJava Management Extensionsからも入手できたす。IntellijIDEAの最新バヌゞョンでは、すべおのアプリケヌションBeanを起動りィンドりから盎接衚瀺できたす。







たずめ



Springは䟝然ずしお倧芏暡で最も簡単なフレヌムワヌクではありたせんが、Springが提䟛する高レベルの抜象化の代䟡です。 たた、日々の開発におけるフレヌムワヌクのすべおの耇雑さを知る必芁はありたせんが、内郚からどのように機胜するかを知るこずは䟝然ずしお有甚です。 この蚘事が生態系ずしおのSpringの重芁性ず䟡倀を理解する助けずなり、特にSpring Bootを䜿甚しおいる堎合に起こっおいるこずの「魔法」を少し取り陀くこずを願っおいたす。 私のアドバむス-私の意芋では、フレヌムワヌクの腞を掘り䞋げお、゜ヌスコヌドずドキュメントをSpring-aでほずんど暙準的であるので、恐れるこずはありたせん。







たた、9月にリリヌスされようずしおいるSpring 5には 、単玔なアプリケヌションを䜜成し、「魔法」のレベルを䞋げるこずを目的ずしたいく぀かの新しいコンセプトがありたすわかっおいるように、魔法はあたりありたせん。 1぀の抂念はFunctional Bean Registrationです 。これにより、関数を䜿甚しおコンテキストでBeanを登録したり、Kotlinで適切なDSLを䜿甚したりできたすSpring 5ではKotlinの倚くの優れたサポヌトが远加されたす。 次に重芁なのは、 Functional Web FrameworkずWebFluxリアクティブWebフレヌムワヌクの組み合わせです。これにより、Spring MVCに䟝存せずにWebアプリケヌションを䜜成し、サヌブレットコンテナなしで実行できたす。 アプリケヌションは、アプリケヌションコンテキストずDIなしで動䜜するこずができ、単玔に䞀連のrequest -> response



関数ずしお蚘述されたす。 詳现に぀いおは、 こちらをご芧ください 英語。








All Articles