[Código fuente del marco] El método de agregar objetos al contenedor IOC subyacente del código fuente de Spring

inserte la descripción de la imagen aquí

1. Introducción al método de agregar objetos al contenedor Spring

  • Usar archivos de configuración XML
    • Utilice la etiqueta <bean> en el archivo de configuración XML para definir el bean y cargar e inicializar el bean a través de contenedores como ClassPathXmlApplicationContext.
  • Usar anotaciones
    • Use anotaciones proporcionadas por Spring, como @Component, @Service, @Controller, @Repository, etc. para identificar beans
    • Luego cargue e inicialice el Bean a través de escáneres de anotaciones como @ComponentScan.
  • Configurar usando Java
    • Los beans se pueden configurar mediante código Java, como el uso de anotaciones @Configuration y @Bean para definir beans
    • Luego cargue e inicialice el Bean a través de contenedores como AnnotationConfigApplicationContext.
  • Usar la anotación Importar
    • Use la anotación @Import para introducir otras clases de configuración y luego cargue e inicialice beans a través del contenedor
    • La anotación @Import proporciona tres usos
      • Importar directamente
      • Lote de la interfaz ImportSelector
      • ImportBeanDefinitionRegistrar registro de condición

2. operación de importación de Bean de importación de anotaciones

(1) Introducción a las anotaciones de importación

  • La anotación de importación es una anotación en el marco Spring, que se utiliza para introducir otras clases de configuración o clases ordinarias de Java en una clase de configuración.
  • A través de la anotación @Import, los beans definidos en otras clases de configuración o clases de Java se pueden introducir en la clase de configuración actual
  • El nombre de bean predeterminado es [nombre completo de la clase, es decir, nombre del paquete + nombre de la clase]

(2) código fuente de la anotación de importación

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

(3) Caso de importación de combate real

  • Cree interfaces relacionadas con automóviles y beans de entidad de clase
//汽车接口
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 = "奥迪汽车";
}
  • Crear un administrador de clase de configuración
@Configuration
@Import(value = {
    
    BaoMaCar.class, AoDiCar.class, BenChiCar.class})
public class CarBeanManager {
    
    
}
  • prueba de clase principal
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));
    }
}

inserte la descripción de la imagen aquí

3. Operación de Bean de importación por lotes de ImportSelector

(1) Introducción a la importación por lotes de importSelector

  • La interfaz ImportSelector se utiliza para realizar la función de registrar beans dinámicamente, importar objetos [por lotes] en el contenedor, seleccionar dinámicamente los beans que deben registrarse de acuerdo con las condiciones y agregarlos al contenedor Spring.

  • Implemente la interfaz ImportSelector, el método selectImports de esta interfaz devolverá una matriz de cadenas, el valor de la matriz es el nombre de clase completo del componente que se agregará

(2) código fuente de importSelector

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

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

(3) Casos reales

  • Todavía usamos los beans de entidad Car para importarlos al contenedor Spring en lotes y personalizamos el selector para implementar la interfaz 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"};
    }
}
  • Modificar el valor de importación en nuestro Manager
@Configuration
//只需要引入MyImportSelector即可
@Import(value = {
    
    MyImportSelector.class})
public class CarBeanManager {
    
    
}
  • prueba de clase principal
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));
    }
}

inserte la descripción de la imagen aquí

4. Operación Bean de registro dinámico BeanDefinitionRegistrar

(1) Introducción a la interfaz ImportBeanDefinitionRegistrar

  • ImportBeanDefinitionRegistrar es una interfaz en el marco Spring, que se utiliza para realizar la función de registrar beans dinámicamente
  • ImportBeanDefinitionRegistrar puede registrar dinámicamente BeanDefinition con el contenedor Spring en tiempo de ejecución
  • A diferencia de ImportSelector, ImportSelector solo puede devolver el nombre de clase del Bean que debe registrarse
  • Cuando utilice la anotación @Import, introduzca la clase que implementa la interfaz ImportBeanDefinitionRegistrar en la clase de configuración actual para realizar la función de registrar dinámicamente el Bean

(2) Código fuente de 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) Casos reales

  • Ahora tenemos un escenario, cuando BMW, Audi y Mercedes-Benz existen, crean un nuevo vehículo de energía.
  • Crear la clase principal de vehículos de nueva energía.
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NewEnergyCar implements Car{
    
    
    private String name = "新能源汽车";
}
  • Cree un ImportBeanDefinitionRegistrar personalizado
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);
        }
    }
}
  • Configurar el valor de importación en Manager
@Configuration
@Import(value = {
    
    MyImportSelector.class,MyImportBeanDefinitionRegistrar.class})
public class CarBeanManager {
    
    
}
  • prueba de clase principal
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));
    }
}

inserte la descripción de la imagen aquíinserte la descripción de la imagen aquíinserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

(4) Introducción a BeanDefinition

  • Uno de los conceptos más importantes en el contenedor de Spring, es la base del contenedor para crear y administrar instancias de Bean, abstracción y encapsulación de la información de definición de Bean.
  • Describir la información de definición de un bean, incluido el nombre, el tipo, el alcance, los atributos y otra información del bean.
  • La creación y administración de Bean se puede configurar y controlar en detalle, como especificar el alcance del Bean, si se carga de forma diferida, si se inyecta automáticamente, etc.
    inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_47533244/article/details/130692260
Recomendado
Clasificación