Punto de extensión de primavera 2: análisis del principio de beanPostProcessor personalizado

beanPostProcessor es una de las interfaces que he visto con más extensiones al estudiar el código fuente de Spring, como: aop, transacción de primavera, devolución de llamada del método de inicialización, que son todas extensiones e implementaciones de esta interfaz, excepto el marco de primavera, como Dubbo ReferenceAnnotationBeanPostProcessor Esta clase extendida es un postprocesador, que se utiliza para analizar la anotación @Reference

El postprocesador del bean, en el proceso de inicialización del bean, spring ha definido qué método del postprocesador se ejecuta primero y qué método se ejecuta después. Por lo tanto, cuando expandimos, debemos estar familiarizados con la posición de ejecución y la secuencia de estos métodos. Secuencia, de acuerdo con estos, para aclarar en qué paso su empresa necesita expandirse

Solo necesitamos implementarlo de acuerdo con diferentes subclases de beanPostProcess

Prefacio

Independientemente de la clase de extensión que implementemos, debemos considerar dos preguntas:
1. Después de extender, si colocamos nuestra clase de extensión personalizada en el contenedor de resorte.
2. Después de colocarla en el contenedor, ¿seguirá los pasos que imaginamos? call
Para el primer punto, podemos pasar directamente la anotación @Component, poner el beanPostProcessor como un bean ordinario en el beanDefinitionMap, porque en el proceso de inicio de primavera, hay un paso para registrar e inicializar todo el posprocesamiento por separado,
por lo tanto , el primer punto, solo necesitamos recordar, siempre que el beanPostProcessor como un bean se pueda agregar al beanDefinitionMap, Spring nos ayudará automáticamente a inicializar el postprocesador

Con respecto al segundo punto, después de proporcionar una clase de implementación, ¿cómo aplica Spring el beanPostProcessor que definimos al proceso de inicialización? También está relacionado con el beanPostProcessor registrado mencionado anteriormente. Después de que Spring inicialice todos los postprocesadores, pondrá los postprocesadores inicializados en una colección, y Spring llamará al método de postprocesador cada vez En este momento, todos los postprocesadores elegibles serán obtenido de esta lista configurada para filtrar

De hecho, por el principio del mecanismo de extensión del postprocesador en primavera, creo que si entiendo estas dos frases, lo entenderé todo.

Con respecto al primer punto, cómo colocar el postprocesador que proporcionamos en el contenedor de resorte, puede consultar la nota anterior Código fuente de Spring: Registrar postprocesador

Registrar post procesador

El segundo punto:
primero hablemos de nuestro postprocesador personalizado, dónde se almacena en
org.springframework.context.support.PostProcessorRegistrationDelegate # registerBeanPostProcessors ()
Este método es un resorte para inicializar todos los postprocesadores, luego, una vez completada la inicialización, hay una operación más crítica
registerBeanPostProcessors (beanFactory, orderPostProcessors);
registerBeanPostProcessors (beanFactory, nonOrderedPostProcessors);
registerBeanPostProcessors (beanFactory, internalPostProcessors);

Estas tres líneas de código llaman a la misma lógica, pero los parámetros de entrada son diferentes. Observa la lógica de procesamiento específica del método.

private static void registerBeanPostProcessors(
      ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    
    

    for (BeanPostProcessor postProcessor : postProcessors) {
    
    
      beanFactory.addBeanPostProcessor(postProcessor);
    }
  }


  @Override
  public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    
    
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // Remove from old position, if any
    this.beanPostProcessors.remove(beanPostProcessor);
    // Track whether it is instantiation/destruction aware
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
    
    
      this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
    
    
      this.hasDestructionAwareBeanPostProcessors = true;
    }
    // Add to end of list
    this.beanPostProcessors.add(beanPostProcessor);
  }

Lo más importante aquí es la última línea de código, poner beanPostProcess en la lista final privada beanPostProcessors = new CopyOnWriteArrayList <> (); en esta colección, esta colección está en el código fuente detrás, veremos, primero tenga una impresión

¿Cómo entra en vigor el posprocesador personalizado?

Tomemos org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
como ejemplo el quinto método de postprocesador . Este método se llama antes de la inyección de propiedades para determinar si es necesaria la inyección de propiedades.
1. Si este método devuelve falso, significa que no es necesario inyectar propiedades en el bean actual.
2 . Entonces, si tengo un requisito en este momento, necesito procesar la clase PayOrderService. No hay necesidad de inyección de atributos en esta clase. Aquí solo doy un ejemplo. En este momento, puedo proporcionar una clase de implementación InstantiationAwareBeanPostProcessor por mí mismo , y luego implementarlo. En el método postProcessAfterInstantiation () de la clase, se juzga que si el bean actualmente inicializado es payOrderService, devuelve falso.
3. Cabe señalar que si ampliamos la clase de implementación nosotros mismos, debemos agregar el juicio del bean al método de implementación. De lo contrario, todos los beans no realizarán la inyección de propiedades, ¿por qué? Porque cada bean llamará a nuestra propia clase de implementación cuando se inicialice para determinar si inyectar propiedades

Aquí hay un punto para explicar, por qué es el método InstantiationAwareBeanPostProcessor, porque InstantiationAwareBeanPostProcessor hereda BeanPostProcessor, por lo que también es una interfaz de extensión del postprocesador;
para el tercer punto, debemos determinar si el bean debe omitir la inyección de atributos por sí mismo Bean, puede ver el código fuente de Spring. El método de implementación predeterminado básicamente devuelve verdadero, lo que requiere la inyección de atributos.

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

boolean continueWithPropertyPopulation = true;

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    
    
  for (BeanPostProcessor bp : getBeanPostProcessors()) {
    
    
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
    
    
      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
      if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    
    
        continueWithPropertyPopulation = false;
        break;
      }
    }
  }
}

if (!continueWithPropertyPopulation) {
    
    
  return;
}

Este fragmento de código es el procesamiento de postProcessAfterInstantiation. Se puede ver que en el código fuente, primero determinará si el beanDefinition actual es un beanDefinition sintético, y luego determinará si hay una clase de implementación de InstantiationAwareBeanPostProcessor en el contenedor actual.

protected boolean hasInstantiationAwareBeanPostProcessors() {
    
    
  return this.hasInstantiationAwareBeanPostProcessors;
}

¿Cuándo se asignan los procesadores hasInstantiationAwareBeanPostProcessors? Registre el postprocesador anterior en el método addBeanPostProcessor aquí

Después de juzgarlos, recorrerá la colección de listas devuelta por getBeanPostProcessors ()

public List<BeanPostProcessor> getBeanPostProcessors() {
    
    
	return this.beanPostProcessors;
}

Como se mencionó anteriormente, la lista de beanPostProcessors se usará más adelante, que está aquí.
Así que aquí hay una explicación. ¿Cómo se aplica nuestra clase de implementación beanPostProcess personalizada?
En el código fuente de Spring, cada vez que se llama a un método de posprocesador, atravesará todos los posprocesadores en el contenedor y llamará a sus métodos de posprocesador a su vez para su procesamiento.

para resumir

Finalmente, un pequeño resumen, si queremos extender una clase de implementación beanPostProcess, esta clase de implementación debe implementar diferentes interfaces beanPostProcess según lo que queramos hacer, y luego inyectar la clase de implementación en el contenedor Spring a través de la anotación @Component. no es necesario hacer otras operaciones. Spring nos ayudará a completar la llamada para el resto.
Sin embargo, cuando extendamos, debemos comprender cómo se implementa nuestra lógica comercial extendida.

Supongo que te gusta

Origin blog.csdn.net/CPLASF_/article/details/115079069
Recomendado
Clasificación