【フレームワークソースコード】Springソースコードの基盤となるIOCコンテナにオブジェクトを追加する方法

ここに画像の説明を挿入

1. Springコンテナにオブジェクトを追加する方法の紹介

  • XML設定ファイルを使用する
    • XML 構成ファイルの <bean> タグを使用して Bean を定義し、ClassPathXmlApplicationContext などのコンテナを通じて Bean をロードして初期化します。
  • 注釈を使用する
    • @Component、@Service、@Controller、@Repository などの Spring によって提供されるアノテーションを使用して Bean を識別します
    • 次に、@ComponentScan などのアノテーション スキャナーを介して Bean をロードして初期化します。
  • Javaを使用した設定
    • Bean は、@Configuration および @Bean アノテーションを使用して Bean を定義するなど、Java コードを使用して構成できます。
    • 次に、AnnotationConfigApplicationContext などのコンテナを通じて Bean をロードして初期化します。
  • インポートアノテーションを使用する
    • @Import アノテーションを使用して他の構成クラスを導入し、コンテナを通じて Bean をロードして初期化します。
    • @Import アノテーションには 3 つの使用法があります
      • 直接インポート
      • ImportSelector インターフェースのバッチ
      • ImportBeanDefinitionRegistrar 条件の登録

2. importアノテーション import Beanオペレーション

(1) インポートアノテーションの概要

  • import アノテーションは Spring フレームワークのアノテーションで、他の構成クラスや通常の Java クラスを構成クラスに導入するために使用されます。
  • @Import アノテーションを使用すると、他の構成クラスまたは Java クラスで定義された Bean を現在の構成クラスに導入できます。
  • デフォルトの Bean 名は [クラスの完全修飾名、つまりパッケージ名 + クラス名] です。

(2) アノテーションソースコードのインポート

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
    
    
  Class<?>[] value();
}

(3)輸入事例実戦

  • 自動車関連のインターフェースとクラスエンティティBeanを作成する
//汽车接口
public interface Car {
    
    
}

//奔驰类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BenChiCar implements Car{
    
    
    private String name = "奔驰汽车";
}

//宝马类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaoMaCar implements Car{
    
    
    private String name = "宝马汽车";
}

//奥迪类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AoDiCar implements Car{
    
    
    private String name = "奥迪汽车";
}
  • 構成クラスマネージャーを作成する
@Configuration
@Import(value = {
    
    BaoMaCar.class, AoDiCar.class, BenChiCar.class})
public class CarBeanManager {
    
    
}
  • メインクラスのテスト
public class Main {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //扫描指定的包,包括子包
        context.scan("com.lixiang");
        //里面完成初始化操作,核心方法
        context.refresh();
        Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
        beansOfType.forEach((k,v)-> System.out.println(k+"="+v));
    }
}

ここに画像の説明を挿入

3.ImportSelector一括インポートBean操作

(1) importSelector一括インポートの紹介

  • ImportSelectorインターフェースはBeanを動的に登録する機能を実現し、オブジェクトをコンテナに[一括]インポートし、条件に応じて登録が必要なBeanを動的に選択してSpringコンテナに追加する機能を実現します。

  • ImportSelector インターフェイスを実装します。このインターフェイスの selectImports メソッドは String 配列を返します。配列内の値は、追加されるコンポーネントの完全なクラス名です。

(2) importSelectorのソースコード

public interface ImportSelector {
    
    
  //该方法的返回值是一个String数组,用于指定需要注册的Bean的类名。
  String[] selectImports(AnnotationMetadata importingClassMetadata);

  @Nullable
  default Predicate<String> getExclusionFilter() {
    
    
    return null;
  }
}

(3) 実際の事例

  • 私たちは依然として Car エンティティ Bean を使用して Spring コンテナにバッチでインポートし、セレクターをカスタマイズして ImportSelector インターフェイスを実装します。
public class MyImportSelector implements ImportSelector {
    
    
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
    
    
        return new String[] {
    
    "com.lixiang.domain.AoDiCar","com.lixiang.domain.BaoMaCar","com.lixiang.domain.BenChiCar"};
    }
}
  • マネージャーでインポート値を変更します
@Configuration
//只需要引入MyImportSelector即可
@Import(value = {
    
    MyImportSelector.class})
public class CarBeanManager {
    
    
}
  • メインクラスのテスト
public class Main {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //扫描指定的包,包括子包
        context.scan("com.lixiang");
        //里面完成初始化操作,核心方法
        context.refresh();
        Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
        beansOfType.forEach((k,v)-> System.out.println(k+"="+v));
    }
}

ここに画像の説明を挿入

4. BeanDefinitionRegistrar動的登録Bean操作

(1) ImportBeanDefinitionRegistrar インターフェースの概要

  • ImportBeanDefinitionRegistrarはSpringフレームワークのインターフェースであり、Beanを動的に登録する機能を実現するために使用されます。
  • ImportBeanDefinitionRegistrar は実行時に BeanDefinition を Spring コンテナに動的に登録できます
  • ImportSelector とは異なり、ImportSelector は登録する必要がある Bean のクラス名のみを返すことができます。
  • @Importアノテーションを使用する場合は、現在の設定クラスにImportBeanDefinitionRegistrarインタフェースを実装したクラスを導入し、Beanを動的に登録する機能を実現します。

(2) ImportBeanDefinitionRegistrarのソースコード

public interface ImportBeanDefinitionRegistrar {
    
    

  /**
    * @param importBeanNameGenerator 
    * @param annotationMetadata 当前类的注解相关信息
    * @param registry IOC容器里面bean的注册信息
    */
  default void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, 
    BeanDefinitionRegistry registry,
    BeanNameGenerator importBeanNameGenerator) {
    
    

    registerBeanDefinitions(importingClassMetadata, registry);
  }

  /**
    * @param annotationMetadata 当前类的注解相关信息
    * @param registry IOC容器里面bean的注册信息
    */
  default void registerBeanDefinitions(
    AnnotationMetadata importingClassMetadata, 
    BeanDefinitionRegistry registry) {
    
    
  }

}

(3) 実際の事例

  • BMW、アウディ、メルセデス・ベンツがすべて存在するとき、新しいエネルギー車が生まれるというシナリオができました。
  • 新エネルギー車の主力クラスを創出
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NewEnergyCar implements Car{
    
    
    private String name = "新能源汽车";
}
  • カスタム ImportBeanDefinitionRegistrar を作成する
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    
    
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
    
    
        /**
         * 可以通过该方法进行手动注册
         */
        boolean adCar = beanDefinitionRegistry.containsBeanDefinition("com.lixiang.domain.AoDiCar");
        boolean bmCar = beanDefinitionRegistry.containsBeanDefinition("com.lixiang.domain.BaoMaCar");
        boolean bcCar = beanDefinitionRegistry.containsBeanDefinition("com.lixiang.domain.BenChiCar");

        if (adCar && bmCar && bcCar){
    
    
            //IOC容器加个混合对象
            BeanDefinition beanDefinition = new RootBeanDefinition(NewEnergyCar.class);
            beanDefinitionRegistry.registerBeanDefinition("newEnergyCar",beanDefinition);
        }
    }
}
  • Managerでインポートの値を構成する
@Configuration
@Import(value = {
    
    MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class CarBeanManager {
    
    
}
  • メインクラスのテスト
public class Main {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        //扫描指定的包,包括子包
        context.scan("com.lixiang");
        //里面完成初始化操作,核心方法
        context.refresh();
        Map<String, Car> beansOfType = context.getBeansOfType(Car.class);
        beansOfType.forEach((k,v)-> System.out.println(k+"="+v));
    }
}

ここに画像の説明を挿入ここに画像の説明を挿入ここに画像の説明を挿入

ここに画像の説明を挿入

(4) BeanDefinition の概要

  • Spring コンテナの最も重要な概念の 1 つであり、コンテナが Bean インスタンスを作成および管理し、Bean 定義情報を抽象化およびカプセル化するための基礎となります。
  • Beanの名前、タイプ、スコープ、属性などのBeanの定義情報を記述します。
  • Beanのスコープの指定、遅延ロードするかどうか、自動インジェクトするかどうかなど、Beanの作成と管理を詳細に設定および制御できます。
    ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_47533244/article/details/130692260