Punto de extensión Springboot BeanDefinitionRegistryPostProcessor

Insertar descripción de la imagen aquí
Colección de métodos de implementación y principios de funcionamiento de la serie de puntos de extensión Springboot:

Punto de extensión Springboot ApplicationContextInitializer

Punto de extensión Springboot BeanFactoryPostProcessor

Punto de extensión Springboot BeanDefinitionRegistryPostProcessor

Punto de extensión Springboot BeanPostProcessor

Punto de extensión Springboot InstantiationAwareBeanPostProcessor

Punto de extensión Springboot SmartInstantiationAwareBeanPostProcessor

Punto de extensión Springboot ApplicationContextAwareProcessor

Punto de extensión Springboot @PostConstruct

Punto de extensión Springboot InicializandoBean

Punto de extensión Springboot SmartInitializingSingleton

Punto de extensión Springboot CommandLineRunner y ApplicationRunner

Punto de extensión Springboot FactoryBean

Punto de extensión Springboot DesechableBean

El final de la serie de puntos de extensión Springboot: ciclo de vida del Bean

Prefacio

A través de este artículo, me gustaría compartir con ustedes otro punto de extensión de Springboot, BeanDefinitionRegistryPostProcessor. Este tipo de punto de extensión generalmente se denomina postprocesador a nivel de contenedor. El otro tipo es un postprocesador a nivel de Bean; un postprocesador a nivel de contenedor. postprocesador. Se ejecutará una vez después de que se inicialice el contenedor Spring y antes de actualizar. El procesador de reinicio a nivel de Bean se ejecutará antes y después de que se cree una instancia de cada Bean.

1. Características funcionales

  1. El método postProcessBeanDefinitionRegistry () puede agregar, eliminar, modificar y verificar BeanDefintion a través de BeanDefinitionRegistry;

  2. Hereda BeanFactoryPostProcessor, que es una interfaz de extensión a nivel de contenedor. El método org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory se ejecuta después de crear una instancia del contenedor y antes de que se actualice. Es decir, puede realizar algunos cambios más. a BeanDefintion antes de que se actualice el contenedor.

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    
    
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
@FunctionalInterface
public interface BeanFactoryPostProcessor {
    
    
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

En resumen, después de cargar todas las BeanDefinitions y antes de que se cree una instancia del Bean, puede realizar algunas operaciones personalizadas en BeanDefinition implementando la interfaz BeanDefinitionRegistryPostProcessor, como modificar las propiedades BeanDefinition de un bean y registrar manualmente algunos Beans complejos.

Los amigos que no están familiarizados con los principios de Spring pueden sentirse un poco confundidos al ver esto: ¿Qué es BeanDefinition? ¿Qué es BeanDefinitionRegistry? ¿Qué es ConfigurableListableBeanFactory? No te preocupes, te daré una breve explicación aquí y tu comprensión de todo el artículo será más fluida.

1.1 Definición de frijol

Como todos sabemos, uno de los núcleos de Spring es IOC (Inversión de Control). La razón por la cual Spring puede lograr la inversión del control de beans es debido a la función de contenedor de Spring. Antes de que los beans se incluyan en la administración de contenedores de Spring, todos los beans encapsularse de forma abstracta en una instancia de BeanDefinition, y luego se crearán instancias del bean en diferentes momentos según la información de la instancia de BeanDefinition.

En pocas palabras, Dog.java describe los atributos y comportamientos de animales como los perros, y BeanDefinition describe la clase Dog.java.

1.2 Registro de definición de frijol

BeanDefinitionRegistry literalmente significa registrar la información de definición de bean. De hecho, la función de esta clase es la misma que el significado literal, que es administrar BeanDefinition (agregar, eliminar, modificar y verificar);

public interface BeanDefinitionRegistry extends AliasRegistry {
    
    
    //注册beanDefinition
   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
         throws BeanDefinitionStoreException;
    //移除指定的beanDefinition
   void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    //根据beanName查询beanDefinition
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    //判断某个beanDefinition是否已经注册
   boolean containsBeanDefinition(String beanName);
    //获取所有已注册的beanDefinition
   String[] getBeanDefinitionNames();
    //获取所有已注册的beanDefinition的数量
   int getBeanDefinitionCount();
    //判断某个beanDefinition是否已经被使用
   boolean isBeanNameInUse(String beanName);
}

1.3 ConfigurableListableBeanFactory

El contenedor de Spring se mencionó anteriormente. Uno de los núcleos de Spring es el IOC, por lo que el diseño del contenedor de Spring es el núcleo del núcleo. Los contenedores de Spring tienen muchas formas. La forma más básica es BeanFactory. ConfigurableListableBeanFactory hereda indirectamente BeanFactory. Por lo tanto, además de las funciones del contenedor de la versión básica de Spring, la clase de implementación ConfigurableListableBeanFactory también tiene algunas funciones avanzadas. La implementación real predeterminada de Springboot es DefaultListableBeanFactory Los amigos interesados ​​pueden utilizar esto como punto de entrada para profundizar más, pero no entraré en detalles aquí.

Insertar descripción de la imagen aquí

2. Implementación personalizada

2.1 MyBeanDefinitionRegistryPostProcessor

A continuación se utiliza una clase específica MyBeanDefinitionRegistryPostProcessor para implementar la interfaz BeanDefinitionRegistryPostProcessor para explorar el proceso de inicialización y ejecución de la clase de implementación BeanDefinitionRegistryPostProcessor.

Cuando se llama al método postProcessBeanDefinitionRegistry (), la información BeanDefinition de la clase Dog se registra manualmente en Spring;

Cuando se llama al método postProcessBeanFactory (), recupere la información BeanDefinition de la clase Dog y la instancia de la clase Dog del contenedor Spring;

@Data
public class Dog {
    
    
    private String name;
    private String color;
}
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    
    
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    
    
        //手工定义一个beanDefinition实例
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        //给beanDefinition填充属性
        beanDefinition.setBeanClass(Dog.class);
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        PropertyValue propertyValue1 = new PropertyValue("name", "旺财");
        PropertyValue propertyValue2 = new PropertyValue("color", "黑色");
        propertyValues.addPropertyValue(propertyValue1);
        propertyValues.addPropertyValue(propertyValue2);
        beanDefinition.setPropertyValues(propertyValues);
        //注册手工定义的beanDefinition
        registry.registerBeanDefinition("dog", beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
    
        System.out.println("-----------start------------");
        //根据类名取出手工注册的beanDefinition
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dog");
        System.out.println(beanDefinition.getBeanClassName());
        //根据类从容器中取出手工注册的beanDefinition所描述的实例bean
        Dog dog = beanFactory.getBean(Dog.class);
        System.out.println(dog.getName());
        System.out.println(dog.getColor());
        System.out.println("-----------end------------");
    }
}

prueba de unidad

@Test
public void test(){
    
    
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.fanfu");
    Dog dog = ((Dog) context.getBean("dog"));
    System.out.println(dog.getName());
    System.out.println(dog.getColor());
}

2.2 diagrama de clases UML

En el diagrama de clases BeanDefinitionRegistryPostProcessorUML, podemos ver que BeanDefinitionRegistryPostProcessor hereda BeanFactoryPostProcessor, el método postProcessBeanDefinitionRegistry() pertenece a BeanDefinitionRegistryPostProcessor y postProcessBeanFactory() pertenece a BeanFactoryPostProcessor. Todas las clases de implementación que implementan la interfaz BeanDefinitionRegistryPostProcessor Necesito implementar estos dos métodos como puntos de extensión de Springboot Uno de La lógica de su expansión también está en estos dos métodos.

Insertar descripción de la imagen aquí

3. Tiempo de inicialización y ejecución.

A través de la clase personalizada MyBeanDefinitionRegistryPostProcessor se implementa la interfaz BeanDefinitionRegistryPostProcessor, a partir del inicio del proyecto el proceso de ejecución es el siguiente:

  1. Al ejecutar la clase principal del proyecto, se llama a org.springframework.boot.SpringApplication#run;

  2. Después de ingresar al método boot.SpringApplication#run, hay algunas operaciones de configuración para la inicialización del contenedor Spring al principio, hasta que se ejecuta org.springframework.boot.SpringApplication#refreshContext, comienza la actualización del contenedor y se ingresa a la etapa crítica;

  3. En SpringApplication#refreshContext, la lógica de actualización real está en el método org.springframework.context.support.AbstractApplicationContext#refresh;

  4. En el método AbstractApplicationContext#refresh, llame a org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors para comenzar a inicializar y ejecutar postProcessBeanDefinitionRegistry() y postProcessBeanFactory() que implementan la interfaz BeanDefinitionRegistryPostProcessor;

  5. Al ingresar al método AbstractApplicationContext#invokeBeanFactoryPostProcessors, encontramos que se volvió a llamar a org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors();

  6. En el método PostProcessorRegistrationDelegate # invokeBeanFactoryPostProcessors (), postProcessBeanDefinitionRegistry () y postProcessBeanFactory () no se inicializan ni ejecutan directamente, pero se realizan una serie de juicios, el orden de juicio es: 1. Implementación de BeanDefinitionRegistryPostProcessor registrada de antemano a través de AbstractApplicationContext#addBeanFactoryPostProcessor Class; 2. Implementa la interfaz PriorityOrdered; 3. Si se implementa Ordered; 4. Las otras clases de implementación restantes de BeanDefinitionRegistryPostProcessor; el MyBeanDefinitionRegistryPostProcessor personalizado pertenece a la cuarta categoría, por lo que se ejecuta más tarde entre todas las implementaciones. Si desea ejecutarlo con anticipación, puedes considerar los tres métodos anteriores;

  7. Después de ejecutar el método MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry en el método PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(), el método MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory comienza a ejecutarse; de ​​todo el proceso de llamada, postProcessBeanDefinitionRegistry() se ejecuta antes que postProcessBeanF método actory();

A continuación se muestra un diagrama de tiempo que dibujé en función de todo el proceso de llamada. El proceso es realmente complicado, pero la lógica es relativamente clara, por lo que no es difícil de entender. Si desea comprender realmente todo el proceso, la mejor manera es Siga este diagrama y ejecútelo usted mismo. Una vez más, observe el proceso de ejecución de cada nodo clave a través de la depuración.
Insertar descripción de la imagen aquí

4. Clase de implementación interna

Las clases de implementación integradas en spring-boot-starter-web incluyen CachingMetadataReaderFactoryPostProcessor, ConfigurationClassPostProcessor, ConfigurationWarningsPostProcessor, EmbeddedDataSourceBeanFactoryPostProcessor, ImportsCleanupPostProcessor, TestRestTemplateRegistrar, WebTestClientRegistrar, WsdlDefinitionBeanFactoryPostProcessor. Observe cada clase de implementación. Encontrado: Todas son similares , estas clases de implementación integradas son todo en Springboot Las clases internas de BeanDefinitionRegistryPostProcessor registran algunas BeanDefinitions especiales en el contenedor Spring a través de estas clases de implementación internas de BeanDefinitionRegistryPostProcessor. Si amplío y hablo sobre estos Beans en detalle, me temo que no podré terminarlo en todo el día y la noche. Los amigos interesados ​​pueden obtener más información al respecto aquí. No se expandirá más.

5. Resumen

Al ordenar todo el proceso, lo más crítico es en realidad una oración: después de que se inicializa el contenedor Spring y antes de actualizarlo, es decir, después de que el Bean se haya escaneado y registrado como BeanDefinition, y antes de que se cree una instancia formal, puede realice algunas operaciones adicionales implementando BeanDefinitionRegistryPostProcessor.
——————————————
Declaración de derechos de autor: este artículo es un artículo original del blogger de CSDN "Ordinary Trafficker" y sigue el acuerdo de derechos de autor CC 4.0 BY-SA. Adjunte el enlace de la fuente original y esta copia. al reimprimir la declaración.
Enlace original: https://blog.csdn.net/fox9916/article/details/128538625

Supongo que te gusta

Origin blog.csdn.net/tian830937/article/details/132947061
Recomendado
Clasificación