スプリングブート自動アセンブリ(A)

ディレクトリ

序文

        私たちはここにあると私たちは、記事を探索する探索したり、汚染されたサプリメントを持っていると同時に、後で簡単に呼び出すためのダウンノートの形での学習春ブーツの間に記録された最近の関連コースは、誤った希望を、我々は速やかに上げることができ、私は事前にあなたに感謝します!

あなたはそれを開始する前に、私はいくつかの質問に学ぶことを願っています:
1.どのような春の注釈ドライバはありますか?
2、本発明の背景を生成するもので、この機能は?
3、このとは何ですか?
4、どのように達成するために?
5.長所と短所は何ですか?
6、この機能は、仕事で適用することができますか?
それは私が、学ぶことの問題は、学ぶための良い方法だと思う理解するために貢献し、自己の問題です。さて、その後、テーマに。

1、起源

        我々は最初の春の注釈の歴史について簡単な話を取ります。コンセプトノートはちょうどそのような@Transactionalのみのサポートと他の注釈として、浮上しているSpring1.x回、。プロトタイプ注釈システムを持っている春2.xの時代、@Autowired、ノートのこのシリーズの@Controller骨格を導入しました。3.xのは、私たちは春の注釈を受け入れるためのXML設定ファイルの形式を、放棄することができ、@Enableドライブモジュールの概念の導入に加えて、成形春の注釈システムも導入@Configurationクラスコンフィギュレーションと@ComponentScanをスピードアップするための黄金時代でしたしかし、完全に@ImportResource輸入レガシーXML構成ファイルに許可を提供春のXML設定ファイルを、放棄しませんでした。@importまた、1つまたは複数のJavaクラスは、春の豆となっ導入できるようにするために提供。4.Xは、ノート@Conditionalの導入のための条件を改善する傾向があり、組み立てがより柔軟になります。5.Xは現在の時代で、基盤となるコアフレームワークは、現在の状況をSpringBoot2.0、変更は素晴らしいではありませんが、それはまた、@Indexedノートを紹介し、主に起動時のパフォーマンスを向上させるために使用されます。まあ、それは春の注釈の歴史があり、我々はいくつかの問題に春の注釈システムを説明します。

2、春の注釈モード

        
Notesアプリケーションの「コンポーネント」の役割を再生するには、ステートメントのノートのためのモデルです。管理し、オブジェクトの特定の領域を格納するために使用されるノートモードをプレイする役割を倉庫ための春@Repositoryのように。コンフィギュレーションモードが設定されている@サービスは、サービスモデルである@など@Componentモードなどの一般的なコンポーネントがあります。
@Componentはコモンモード成分容器としてバネによってホストされており、任意の標識された成分は@Componentアセンブリ候補がスキャンされています。同様に、そのような候補アセンブリスキャンのような任意の成分のラベルまたみなされる@Serviceとして@Component注釈を、マークされた人。
例えば:

春の注釈 シーン記述 バージョンを起動します
@Componnt 総会モードの注意事項 2.5
@Repository データ・ウェアハウス・モードの注意事項 2.0
@サービス メモサービスモデル 2.5
@コントローラ ウェブコントローラモードの注意事項 2.5
@Configuration クラスコンフィギュレーションモードの注意事項 3.0

だから、どのようにこれらのノートがマークされているクラスは、それを管理するために、春に引き渡さ、またはそれが春を組み立てましたか?次は春の2つの組立方法を見ていきます。

2.1、組み立て方法

  • <コンテキスト:コンポーネント・スキャン>方法
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns="http://www.springframework.org/schema/beans"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd ">

    <context:component-scan base-package="com.loong.spring.boot" />
</beans>

最初はベースパッケージが一定の範囲内にこのプロパティをスキャンすべての@Componentまたはその派生クラスの注釈マーク(クラス)を指定し、途中XML設定ファイルである、彼らは春ビーンとして登録されます。

我々は、すべての明示的なコンフィギュレーション・ファイルとして名前空間、関連付けられるXMLスキーマ仕様、ラベルのニーズことを知っている
のxmlns:=「http://www.springframework.org/schema/context」コンテキスト、およびマッピングプロセスを確立する必要性とそのクラスを、この関係は、クラスパスの/META-INF/spring.handlersファイルに関して維持されています。次のとおりです。

http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/jee=org.springframework.ejb.config.JeeNamespaceHandler
http\://www.springframework.org/schema/lang=org.springframework.scripting.config.LangNamespaceHandler
http\://www.springframework.org/schema/task=org.springframework.scheduling.config.TaskNamespaceHandler
http\://www.springframework.org/schema/cache=org.springframework.cache.config.CacheNamespaceHandler

コンテキストプロセッサContextNamespaceHandler対応する、参照してください。

public class ContextNamespaceHandler extends NamespaceHandlerSupport {
    @Override
    public void init() {
        .....
        registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
        registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
        .....
    }
}

春はここから始まると、initメソッドは、この名前空間で定義され、その後、登録済みのすべての豆パーサと呼ばれ、あなたが見ることができます パーサはComponentScanBeanDefinitionParserです。このクラスの具体的な処理は、興味のある学生は、理解するために行くことができ、ここでそれらを繰り返すことはしません。

  • @ComponentScan方法
@ComponentScan(basePackages = "com.loong.spring.boot")
public class SpringConfiguration {

}

二つ目は、コメントフォームでもスキャン範囲basePackages属性の指定に依存しています。

すべてのコンフィギュレーション・パーサークラスのノートの特定のライフサイクル内で作成された起動時の春、そして@ComponentScanプロセッサがComponentScanAnnotationParserで、興味のある学生は、理解して行くことができるだけでなく、ここでそれらを繰り返すことはしません。

2.2導出

私たちは、本文中に記載の導出を見て、カスタム注釈の方法を使用します。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repository
public @interface FirstLevelRepository {
    String value() default "";
} 

私たちは、の定義から見ることができます
(「文字列値()デフォルト」、@FirstLevelRepositoryノート注釈と現在の@Repositoryをマークし、@Repositoryは@Componentと一貫性のある注釈の属性をマークした )、 その後、あなたは現在の注釈が含まれてい表すことができ
@Repositoryと@Component機能。

導出事実は、例えば、複数のレベルに分けることができる
@SprintBootApplication - > @SpringBootConfiguration - > @Configuration - > @Componentは、
レベルの数を導出することが@Componentを見ることができるが、スプリング4.0バージョンのこのマルチレベル誘導体が始まっサポート、Spring3.0のサポートのみ2層。

3、春@Enableドライブモジュール

        前述Spring3.Xが、それは注釈モードを採用するだけでなく、黄金時代です、またサポートするために始めた「@Enableモジュールドライバを。」いわゆる「モジュール」は、機能的な構成要素を指すコレクションの同じフィールド、そのようなウェブMVCモジュールとして、組み合わせることにより形成された単一のユニット、AspectJのプロキシモジュール、キャッシュ(キャッシュ)ブロック、JMX(Javaの管理拡張)モジュール、非同期(非同期処理を持っています)モジュール。この「モジュール」という概念は、その後の春、春ブーツと春のクラウド版で使用されている以下のように、このモジュール式のノートには、接頭辞として@Enable、次のとおりです。

フレームワークの実装 @Enable commentモジュール アクティベーションモジュール
春のフレームワーク @EnableWebMvc ウェブMVCモジュール
/ @EnableTransactionManagement 物事管理モジュール
/ @EnableWebFlux ウェブフラックスモジュール
春ブーツ @EnableAutoConfiguration 自動アセンブリモジュール
/ @EnableConfigurationProperties モジュール構成結合特性
/ @ EnableOAuth2Sso OAuth2シングルサインオンモジュール
春の雲 @EnableEurekaServer ユーレカサーバーモジュール
/ @EnableFeignClients 装うクライアントモジュール
/ @EnableZuulProxy Zuulサービスゲートウェイモジュール
/ @EnableCircuitBreaker サービス吹きモジュール

有意性は、組立工程の詳細は、アセンブリモジュールコンポーネントのコレクションをスクリーニング駆動モジュールの導入を簡素化することです。高いコストと負荷メカニズムの原則を理解しながら、しかし、モデルは手動でトリガされなければならないこと、ノートに設定ビーンをマーク。さて、春は@Enableモジュールにそれを達成する方法ですか?主に2つの方法があります。

3.1、春のフレームワークの実装@Enable

  • 注釈駆動型に基づいて
    まず、@EnableWebMvcの実装を参照:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
    
}

@Configuration 
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    ... 
}

この実装パターンは、これはすべて知っている@EnableWebMvcがWeb MVCモジュールを活性化するために使用され、我々の構成クラスは、HandlerMappingように、であることを、主に輸入コンフィギュレーションクラス@importによってDelegatingWebMvcConfiguration、および@Configurationノートをマークし、そのクラスで
、HandlerAdapterこれらおよびMVC関連するコンポーネントは、いわゆるモジュラーコンセプトであるこの構成のカテゴリに組み立てられています。

  • ベースのプログラミングインタフェース

同じインターフェイスベースのプログラミングの最初の基準@EnableCachingを達成するための2つの方法があります。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CachingConfigurationSelector.class) 
public @interface EnableCaching {
    ...
}

public class CachingConfigurationSelector extends AdviceModeImportSelector<EnableCaching> {
    
    @Override
    public String[] selectImports(AdviceMode adviceMode) {
        switch (adviceMode) { //switch语句选择实现模式
            case PROXY:
                return new String[]{AutoProxyRegistrar.class.getName(), ProxyCachingConfiguration.class.getName()};
            case ASPECTJ:
                return new String[]{AnnotationConfigUtils.CACHE_ASPECT_CONFIGURATION_CLASS_NAME};
            default:
        }
    }
}

このようにインタフェースは、主ImportSelector(AdviceModeImportSelector ImportSelector器具インタフェース)継承され、その後さらに、この方法はより柔軟であるアノテーションを駆動に比べて、1つまたは複数のクラスを選択する基準動的に導入することによって、selectImportsメソッドを実装します。

第二の基準@EnableApolloConfig実装。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(ApolloConfigRegistrar.class)
public @interface EnableApolloConfig {
    ....
}
public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        ....

        BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(),
        PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues);

        BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(),
        PropertySourcesProcessor.class);

        BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(),
        ApolloAnnotationProcessor.class);

        BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class);
        BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class.getName(), SpringValueDefinitionProcessor.class);

        BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(),
            ApolloJsonValueProcessor.class);
    }
}

直接手動BeanDefinitionRegistryレジスタによる組立方法、そのようなregisterBeanDefinitionsオーバーライドと関連するモジュールで、導入することによって、インタフェースImportBeanDefinitionRegistrar @importを実装するアプローチクラス。
次に、我々は両方で@Enableカスタムモジュールを実現します。

3.2、@Enable用カスタムモジュール

  • 注釈駆動型に基づいて
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {
}
@Configuration
public class HelloWorldConfiguration {

    // 可以做一些组件初始化的操作。

    @Bean
    public String helloWorld(){ 
        return "hello world";
    }
    // ....
}
@EnableHelloWorld
public class EnableHelloWorldBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloWorldBootstrap.class)
                .web(WebApplicationType.NONE).run(args);
        String helloWorld = context.getBean("helloWorld",String.class);
        System.out.println(helloWorld );
    }
}

ここでは、@EnableHelloWorldコメントをカスタマイズし、その後、この構成クラスでのhelloWorld初期定義された自己設定クラスHelloWorldConfigurationをインポートする@import。

  • ベースのプログラミングインタフェース
    最初に基づいていImportSelectorインターフェース:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldImportSelector.class)
public @interface EnableHelloWorld {
}
public class HelloWorldImportSelector implements ImportSelector {
    /**
     * 这种方法比较有弹性:
     *  可以调用importingClassMetadata里的方法来进行条件过滤
     *  具体哪些方法参考:https://blog.csdn.net/f641385712/article/details/88765470
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        if (importingClassMetadata.hasAnnotation("com.loong.case3.spring.annotation.EnableHelloWorld")) {
           return new String[]{HelloWorldConfiguration.class.getName()};
        }
    }
}
@Configuration
public class HelloWorldConfiguration {
    // 可以做一些组件初始化的操作

    @Bean
    public String helloWorld(){ 
        return "hello world";
    }
    // ....
}
@EnableHelloWorld
public class EnableHelloWorldBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloWorldBootstrap.class)
                .web(WebApplicationType.NONE).run(args);
        String helloWorld = context.getBean("helloWorld",String.class);
        System.out.println(helloWorld );
    }
}

ここでは、またimportingClassMetadata.hasAnnotation(「com.loong.case3.spring.annotation.EnableHelloWorld」)によって書き換えの過程でImportSelectorインタフェースを実装HelloWorldImportSelector @importクラス、分析を導入することで、カスタム注釈を@EnableHelloWorldクラスマーク@EnableHelloWorld注釈、インポートHelloWorldConfigurationクラス初期化するかどうか。

ImportBeanDefinitionRegistrarインタフェース上の第二:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldRegistrar.class)
public @interface EnableHelloWorld {
}
public class HelloWorldRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
        if (annotationMetadata.hasAnnotation("com.loong..case4.spring.annotation.EnableHelloWorld")) {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(HelloWorldConfiguration.class);
            beanDefinitionRegistry.registerBeanDefinition(HelloWorldConfiguration.class.getName(), beanDefinition);
        }
    }
}
@Configuration
public class HelloWorldConfiguration {
    public HelloWorldConfiguration() {
        System.out.println("HelloWorldConfiguration初始化....");
    }
}
@EnableHelloWorld
public class EnableHelloWorldBootstrap {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableHelloWorldBootstrap.class)
                .web(WebApplicationType.NONE).run(args);
    }
}

ここでHelloWorldRegistrarで直接登録HelloWorldConfiguration使用BeanDefinitionRegistryです。

4、春の組立条件

        一連の操作はアセンブリ豆、すなわち予め定めビーンか否かを判断組み立てることによって組み立ての状態を指します。@Profileと@Conditional、@Profileも春4.0後@Conditionalによって達成されるので、ここで我々が実装@Conditionalについて話:達成するために、主に2つの方法があります。

@Conditional(HelloWorldCondition.class)
@Component
public class HelloWorldConfiguration {
    public HelloWorldConditionConfiguration (){
        System.out.println("HelloWorldConfiguration初始化。。。");
    }
}
public class HelloWorldCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        // ...
        return true;
    }
}

ここでHelloWorldConfigurationカスタム設定クラスは、クラスラベル@Conditional HelloWorldCondition輸入注釈は、条件クラスがインタフェースを実装する必要があり、その後、matchesメソッドをオーバーライドし、二つのパラメータによって、プロセスのコンテキストデータとメタデータの直列に取得することができます最終的には、クラス初期化するかどうかを判断するトゥーレまたはfalseを返します

5、要約

        注釈主導春の概念は終わりに来て、この記事の内容は簡単にレビューへの最後で、この記事では、Springのアノテーションに関連する概念について主に:春のパターン注釈、@組立ドライブモジュールを有効にして、春の用語。
スプリング注釈モードは、コアは、注釈モードをマークされているすべてが@Component、実際@Componentプロセスを探し組立方法の対応する二種類あります。スプリング@Enableモジュールコアは、コンフィギュレーションクラス内のこの初期化モジュールを実現するために構成@Enableアノテーションのクラス@import、および関連するコンポーネントを介して導入されます。
あなたが見ることができる、春のコンポーネントアセンブリは、手動で複数の注釈をマークする必要があり、自動化を持っていない、と相互に協力する必要があるので、次の章の間、私たちは自動組立を達成するためにどのように春ブーツ春の注釈ベースのドライブについて何かを言うだろう。

これらには、以上のように、この章の内容は、あるか、前方に入れてください、私は感謝して追加する必要があります記事に誤りがあります。



参考:

「春のブートプログラミングのアイデア」

おすすめ

転載: www.cnblogs.com/loongk/p/11970246.html