【Springおでん】Spring容器にBeaビンを登録する3つの方法を検討します.

20674 ワード

Springを容器に登録するBeanの3つの方法を検討します.
重点的に@Importの実現の3種の方式を理解します.
前提の概要
Spring容器にBeanを登録する3つの方法
  • @ComponentScan、@Compnet
  • を通じて
  • @Bean方式で
  • @Import方式で
  • 直接配置類を導入する
  • Import Selector実装クラス
  • を導入する.
  • ImportBeanDefiniteRegistar実装クラス
  • を導入します.
    3つの方式の違いと応用シーン
    @Importと@Component、@Bean方式の違い
    @Component、@Beanの違い:
  • @ComponentScan、@Componenetはコンポーネント声明とスキャンの方式を通じてBeanを登録しています.最も一般的な方法の一つで、パケットスキャン、一括声明のコンポーネントを提供しています.スキャンされたすべてのコンポーネントをSpring容器に登録してもいいです.Componentは常にクラスを修飾して一つのコンポーネントにしています.一般的には本プロジェクトで自分で定義したクラスです.このように声明します.比較的簡単です.
  • 、@Beanは通常、@Configration(@Componentと区別されていません)を組み合わせて使用していますが、@Component方式によって宣言されているクラスで修飾方法を提供し、単一Benの登録を提供し、通常は修飾方法を用いて、この方法の返却先をSpring容量に登録します.宣言するBeanのクラスが第三者Jarパケットで宣言されている場合、このような経路は一般的には@ComponentScanのスキャン範囲内にないので、@Componentは有効ではないです.この場合@Benまたは@ImportでSpring容器
  • に登録できます.
    @Importと他の違い:
  • @ImportはSpring 3.0以降に提供されたもので、一つのクラスをSpring容器に素早く登録することができます.実際の開発では、モジュールの組み立てに合わせて、第三者のコンポーネント、Spring Boot自動化組立などを登録します.しかし、我々はSpringのソースコードを読むとき、これは非常に一般的です.
  • @Import 3種方式の違い(ポイント理解)
    @Import方式には三つのシードがあります.
  • 直接配置類を導入する
  • Import Selector実装クラス
  • を導入する.
  • ImportBeanDefiniteRegistar実装クラス
  • を導入します.
    違い:
    最初の直接配置類を導入する方式は比較的直接的で、ある種類を直接容器に登録します.Spring 3.0から提供されます.
    第二の方式と第三の方式は第一の方式よりもっと柔軟で、Spring 3.1以降に提供されます.
    第二の方法は、Selector実装クラスにおいて、異なるコンポーネントを条件によって登録することができ、着信パラメータのよりも、異なるコンポーネントを登録することができる.これは最初の方法と違って、直接にコンポーネントを書き終えました.
    第三の方式では、より柔軟に、手動登録ビーンをサポートして、ビーンDefinite段階でコンポーネントを登録して、プログラムが走る時にビーンを動的に登録してもいいです.ビーンDefiniteに基づいて動作するので、このコンポーネントを動的に代行して、結果をSpring容器に登録してもいいです.
    すなわち、第一は直接導入であり、第二は条件によって異なるビーンを登録することができ、第三は条件によって異なるビーンを登録するだけでなく、ビーンメタデータを修正して動的な修正ビーンに到達させ、修正されたビーンを容器に登録することができる.
    シーン:
  • の第一の実現は、直接的な導入プロファイルは、Springソース-@EnableWebMvcの注釈で
  • を体現することができます.
  • の第二の実施形態では、Import Selectorは、SpringBootの@EnableAutoConfiguration注釈に
  • を表現することができる.
  • 第3の実施形態では、ImportBeanDefiniteRegistarは、Spring Cloudの@EnableFeignClients注釈において
  • を体現することができる.
    三つの方式の実現
    @ComponentScan、@Compnetで登録します.
    パッケージスキャンとコンポーネントを通して注釈を宣言する方式は、私達が開発する中で最も一般的なビーン登録の方式です.
  • は、一般的に、ある種類がBeaBenであることを宣言し、Spring容器に登録するために使用される
  • .
  • SpringBoot中@ComponentScanは、ブートクラス@Spring BootAppleの注釈において、
  • と宣言されています.
  • の効果はXMLプロファイルの
  • と同等です.
    原理とは:
  • まず、@Compnetを通じてコンポーネント類
  • を注釈します.
  • その後、@ComponentScan注釈を設定し、登録が必要なコンポーネント
  • をスキャンする.
    一般的な属性名
    タイプ
    説明
    include Filters
    Filter[]
    スキャン導入タイプのフィルタルールを指定します.
    exclude Filters
    Filter[]
    スキャン排除タイプのフィルタルールを指定します.
    普通は@Service,@Configuration,@Controllerなどのモードの注釈を使っていますが、これらもこのような方式で登録されていますか?
    これらの注釈はすべて@Componentコンポーネントの派生にすぎないので、名称が違う@Componentだけです.名前は標識的な役割を果たしています.本当に効果があるのは@Componentの注釈です.
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Configuration {
         
    }
    
    例えば@Configrationのコメントを見ることができます.中には@Componeのコメントがあります.そして、特別なものはありません.
    @Bean方式で登録する
    @Bean方式でBeanを登録するのも私達の開発でよく使われている開発方式です.
  • @Beanは、修飾方法および注釈のために使用されてもよい.
  • は、一般的に、@Bean修飾の方法を、このBeanを生成するためのソースと見なしている
  • .
  • 通常、私たちも@Configrationで修飾された構成クラスの中で声明します.
  • の効果はXMLプロファイルの
  • と同等です.
    最も一般的な使い方は:
  • は方法でマークされ、方法の戻り値をSpring容器に登録し、種類は戻り値タイプであり、bean_idはデフォルトでは方法名
  • である.
    たとえば
    @Configuration
    public class MyConfig(){
         
    
    	@Bean 
    	public String hello(){
         
    		return "hello world";
    	}
    
    }
    
    ここでは、オブジェクトはBeanとして宣言され、Spring容器に登録されたIDがハローワールドのStringオブジェクトとして生成されます.
    @Import方式で登録する
    @Import方式の使用も頻繁で、もっと多い場合、Springフレームのソースコードを読む時に出会うことができます.
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Import {
         
    
    	/**
    	 * {@link Configuration}, {@link ImportSelector}, {@link ImportBeanDefinitionRegistrar}
    	 * or regular component classes to import.
    	 */
    	Class<?>[] value();
    
    }
    
    ソースから見られます.
  • にはメンバー属性が一つしかありません.クラス型変数value
  • @Import可修飾類、注釈等…
  • コメントから分かるように、valueは通常3つの選択肢があります.
  • は直接に1つの構成クラス(たとえば@Configration)
  • を指します.
  • は、1つのImportSelectorインターフェース実装クラス
  • を直接指す.
  • は、ImportBeanDefinitionRegistrar実装クラス
  • を直接指す.
    リボン:
  • @Importは、クラスや注釈などを修飾することができます.
  • @Importは、Spring容器に直接登録される1つ以上のクラスを指定できます.これらのクラスは、他の注釈の修飾を必要としないことができます.例えば、@Configration
  • @Importで指定されたvalue属性は大きく三つの種類に分けられます.普通の配置類、Import Selector実現類、ImportBenDefinitionRegistar実現類、後の二つはSpring 3.1後に提供されるオプション方式で、前者はSpring 3.0であり、後者は前者より柔軟な
  • です.
    @Import直接Benを導入する
    第1ステップ、カスタム注釈EnableHello
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(MyConfiguration.class)
    public @interface EnableHello{
         
    }
    
    第二ステップ、カスタム設定クラス
    public class MyConfig{
         
    }
    
    第三ステップ、コメントを発表します.
    @EnableHello
    @SpringBootApplication
    public class DemoApplication {
         
    
        public static void main(String[] args) {
         
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
    SpringBootブートガイドのようなコンポーネントで@EnbaleHelloコメントをすることで、MyConfigの一般的な構成クラスがSpring容器に直接登録されます.
    Import Selectorインターフェースを実現し、Beanクラス名配列に戻ります.
    第1ステップ、カスタム注釈EnableHello
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(MyConfiguration.class)
    public @interface EnableHello{
         
    }
    
    第二ステップ、カスタム設定クラス
    public class MyConfig{
         
    }
    
    第三段階、カスタムxSelector実現類
    public class HelloImportSelector implements ImportSelector {
         
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
         
            return new String[]{
         MyConfig.class.getName()};
            //              ,  com.example.demo.config.MyConfig
        }
    }
    
    第三ステップ、コメントを発表します.
    @EnableHello
    @SpringBootApplication
    public class DemoApplication {
         
    
        public static void main(String[] args) {
         
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
    ここでは条件によって異なるビーンを登録していませんが、ユーザー定義の注釈には1つのvalueが定義されています.selectImports()の方法では、注釈のメタデータを取得してvalueとは何かを得ることができます.このvalueによって登録するビーンの名前配列に対応して返送することができます.
    ImportBeanDefinitionRegistarインターフェースを実現し、カスタムBean登録します.
    第一歩、声明の注釈、@Importは私達のImportBeanDifinitionRegistar実現類を実行します.
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(MyImportBeanDefinitionRegistrar .class)
    public @interface EnableHello{
         
    }
    
    二番目のステップは、Beanとしてのクラスを宣言しますが、登録されていません.属性nameはデフォルトでは値がありません.
    @Data
    public class Hello {
         
    
        private String name;
    
    }
    
    第三ステップ、カスタムImportBenDifinitionRegistar実現クラス
    public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
         
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
         
        	//  Hello  BeanDefinition
            BeanDefinition beanDefinition = new RootBeanDefinition(Hello.class);
            //  Hello         
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            //  name    ,     
            ((MutablePropertyValues) propertyValues).add("name","snailmann");
            //     Bean      BeanDefinitionRegistry 
            registry.registerBeanDefinition("hello",beanDefinition);
        }
    }
    
    第四ステップ、クラス宣言を起動して、ユーザー定義の注釈を付ける.
    @EnableHello
    @SpringBootApplication
    public class Demo4Application {
         
    
        public static void main(String[] args) {
         
            ApplicationContext context = SpringApplication.run(Demo4Application.class, args);
            Hello hello = (Hello) context.getBean("hello");
            System.out.println(hello);
    
        }
    
    }
    
    出力結果は:
    Hello(name=jerry)
    
    ここから、ImportBeanDifinitionRegistarの機能は最も強力であり、Selectorの機能を実現するだけでなく、運行中にBenのメタデータを動的に修正して、Beanを動的に登録することができます.
    私たちが知っているように、@EnbaleFeign Clients注釈はこのように実現されます.私が予想しているのは、@Feign ClientがAPIを宣言し、@EnbaleFeign Clientsが指定したregisterは@Feign Clienntのクラスを探しています.このようなBeanメタデータを修正して、動的エージェントのような感じがします.これらのアプリはシェル仕様なので、レギターはhttpを実現するために要求する機能です.
    結び目
  • の詳細は、私たちは設定クラスではありません.Import Selector実装クラス、ImportBenDefinitionRegistar実装クラスで声明@Configration、@Comppenentなどのパターンの注釈がありません.
  • 参考資料
  • SpringBoot-容器に登録するBeaビンの様々な方法-著者:東京の冷えやすい
  • ダイナミック登録bean、Spring公式コース:ImportBenDefinitionRegistar-著者:李佳明
  • を使用します.
  • ImportBenDefinitionRegistarインターフェースを介してbeanの動的注入を実現する-著者:Top_Beaer