Aplicación de interfaz extendida clásica de Spring: BeanPostProcessor

Nota: En abril y mayo se completará un nuevo resumen de ideas básicas.

1. Resumen de conocimientos básicos de BeanPostProcessor

BeanPostProcessor es un procesador a nivel de bean que se utiliza para personalizar instancias de bean después de la creación de instancias e inicialización del bean, como verificación de atributos, procesamiento unificado de beans personalizados, etc.

Se definen dos métodos en la interfaz BeanPostProcessor:

  • El método postProcessBeforeInitialization aplica BeanPostProcessor a una instancia de bean determinada antes de cualquier devolución de llamada de inicialización de bean (como el método afterPropertiesSet de la interfaz InitializingBean, un método de inicialización personalizado), y su valor de retorno puede ser el propio bean o su clase contenedora.

  • El método postProcessAfterInitialization se llama después del método de inicialización de devolución de llamada del bean.

Proceso de implementación: registro - ejecución de postProcessBeforeInitialization - ejecución de postProcessAfterInitialization

Si queremos completar la creación de instancias, la configuración y otros métodos de inicialización de beans en el contenedor Spring, debemos agregar algún procesamiento lógico propio antes y después. Necesitamos definir una o más clases de implementación de la interfaz BeanPostProcessor y luego registrarlas en el contenedor Spring IoC.

Ilustración del proceso de creación de instancias de Bean in Spring:

 Aviso:

1. Ambos métodos en la interfaz deben devolver el bean entrante y no pueden devolver nulo. Si se devuelve nulo, no obtendremos el objetivo a través del método getBean.

2. BeanFactory y ApplicationContext tratan a los postprocesadores de beans de forma ligeramente diferente. ApplicationContext detectará automáticamente todos los beans que implementan la interfaz BeanPostProcessor en el archivo de configuración, los registrará como postprocesadores y luego los llamará cuando el contenedor cree el bean. Por lo tanto, implementar un postprocesador no es lo mismo que implementar otros beans. ... No hay diferencia. Cuando se implementa usando BeanFactory, el postprocesador de bean debe registrarse explícitamente mediante código. El método de registro se define en la interfaz ConfigurableBeanFactory en el sistema de herencia de contenedores de IoC.

/**  
 * Add a new BeanPostProcessor that will get applied to beans created  
 * by this factory. To be invoked during factory configuration.  
 * <p>Note: Post-processors submitted here will be applied in the order of  
 * registration; any ordering semantics expressed through implementing the  
 * {@link org.springframework.core.Ordered} interface will be ignored. Note  
 * that autodetected post-processors (e.g. as beans in an ApplicationContext)  
 * will always be applied after programmatically registered ones.  
 * @param beanPostProcessor the post-processor to register  
 */    
void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

Además, no marque el BeanPostProcessor como inicializado de forma diferida. Porque si haces esto, el contenedor Spring no los registrará y no se aplicará la lógica personalizada. Si utiliza el atributo 'default-lazy-init' en la definición del elemento <beans />, asegúrese de que cada una de sus etiquetas BeanPostProcessor sea 'lazy-init="false"'.

2. Análisis de la aplicación práctica de BeanPostProcessor.

Hay muchos escenarios de aplicación prácticos de la interfaz BeanPostProcessor en el marco Spring, aquí hay algunos ejemplos:

  1. Inyección de propiedades : al implementar la interfaz BeanPostProcessor, puede realizar una inyección personalizada de propiedades del Bean después de crear una instancia del Bean y antes de la inicialización. Por ejemplo, puede modificar o asignar valores a las propiedades del Bean en el método postProcessBeforeInitialization de BeanPostProcessor para lograr requisitos personalizados para la inyección de propiedades.
  2. Preprocesamiento de AOP : puede realizar un preprocesamiento relacionado con AOP en el Bean después de crear una instancia del Bean y antes de la inicialización implementando la interfaz BeanPostProcessor. Por ejemplo, puede generar dinámicamente un objeto proxy para Bean en el método postProcessBeforeInitialization de BeanPostProcessor para implementar funciones orientadas a aspectos AOP.
  3. Lógica de inicialización personalizada : puede implementar una lógica de inicialización personalizada para Bean durante la fase de inicialización de Bean implementando la interfaz BeanPostProcessor. Por ejemplo, puede realizar algunas operaciones de inicialización, como inicialización de datos, carga de recursos, etc., en el método postProcessAfterInitialization de BeanPostProcessor.
  4. Verificación de datos : puede verificar los datos en el Bean después de que se inicializa el Bean implementando la interfaz BeanPostProcessor. Por ejemplo, puede verificar los datos en el Bean en el método postProcessAfterInitialization de BeanPostProcessor para garantizar la legalidad e integridad de los datos.
  5. Reciclaje de recursos : al implementar la interfaz BeanPostProcessor, los recursos del Bean se pueden reciclar antes de que se destruya el Bean. Por ejemplo, puede realizar operaciones como liberar y cerrar recursos en el método postProcessBeforeDestruction de BeanPostProcessor para garantizar una liberación razonable de recursos.

Cabe señalar que al implementar la interfaz BeanPostProcessor, debe manejar el ciclo de vida del Bean con cuidado para evitar introducir efectos secundarios innecesarios y problemas potenciales. Al utilizar la interfaz BeanPostProcessor, debe considerar cuidadosamente si realmente necesita personalizar el Bean, así como el tiempo y el método de procesamiento según las necesidades específicas.

3. Visualización de aplicaciones prácticas

(1) Inyección de atributos

Al implementar la interfaz BeanPostProcessor, puede realizar una inyección personalizada de propiedades del Bean después de crear una instancia del Bean y antes de la inicialización. Por ejemplo, puede modificar o asignar valores a las propiedades del Bean en el método postProcessBeforeInitialization de BeanPostProcessor para lograr requisitos personalizados para la inyección de propiedades.

Defina MyBeanPostProcessor para implementar la interfaz BeanPostProcessor y anular dos de sus métodos postProcessBeforeInitialization y postProcessAfterInitialization.

En el método postProcessBeforeInitialization, la inyección personalizada de atributos se realiza en el Bean tipo MyBean, cumpliendo con los requisitos personalizados para la inyección de atributos (este es solo un ejemplo simple, la lógica de procesamiento en aplicaciones reales puede ser más compleja y el procesamiento personalizado se realiza de acuerdo con necesidades específicas. .)

package org.zyf.javabasic.springextend.beanpostprocessorext;

import lombok.Data;

/**
 * @author yanfengzhang
 * @description
 * @date 2023/4/16  23:54
 */
@Data
public class MyBean {
    private String myProperty;

    public void doSomething(){
        System.out.println("MyBean.doSomething()执行,myProperty="+myProperty);
    }
}

En aplicaciones reales, MyBean puede ser un objeto comercial, como una clase de implementación de lógica comercial, un objeto de acceso a datos, etc., según sus necesidades comerciales. MyBean es solo un marcador de posición. Puede definir y nombrar su propio tipo de Bean de acuerdo con sus necesidades comerciales reales y la convención de nomenclatura de los objetos comerciales. En aplicaciones reales, debe reemplazar MyBean con el nombre de clase del objeto comercial que realmente utiliza para poder realizar el procesamiento correspondiente en MyBeanPostProcessor.

Ejemplo de configuración

Para utilizar este BeanPostProcessor personalizado, debe registrarlo en el contenedor Spring. Hay dos formas:

a través del archivo de configuración

<!-- 配置文件中的注册方式 -->
<bean class="org.zyf.javabasic.springextend.beanpostprocessorext.MyBeanPostProcessor" />

Configurando clases a través de Java

package org.zyf.javabasic.springextend.beanpostprocessorext;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author yanfengzhang
 * @description
 * @date 2023/4/16  23:58
 */
@Configuration
public class MyAppConfig {
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }
}

Visualización de código

package org.zyf.javabasic.springextend.beanpostprocessorext;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author yanfengzhang
 * @description
 * @date 2023/4/16  23:53
 */
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 在 Bean 初始化前的处理逻辑
        if (bean instanceof MyBean) {
            MyBean myBean = (MyBean) bean;
            // 对 MyBean 的属性进行自定义注入
            myBean.setMyProperty("自定义属性");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 在 Bean 初始化后的处理逻辑
        return bean;
    }
}

De esta manera, el contenedor Spring llamará al método postProcessBeforeInitialization en MyBeanPostProcessor antes de crear una instancia e inicializar el bean para implementar el procesamiento personalizado de la inyección de propiedades. Cabe señalar que MyBeanPostProcessor debe registrarse como Bean en el contenedor Spring para poder ser reconocido por el contenedor Spring y ejecutar su lógica.

Nuestro código de verificación es el siguiente:

package org.zyf.javabasic;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.zyf.javabasic.springextend.beanpostprocessorext.MyBean;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * 描述:启动入口类
 *
 * @author yanfengzhang
 * @date 2019-12-19 18:11
 */
@SpringBootApplication
@ComponentScan(basePackages = {"org.zyf.javabasic"})
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@EnableSwagger2
public class ZYFApplication {

    public static void main(String[] args) {

        ApplicationContext context = SpringApplication.run(ZYFApplication.class, args);

        // 使用 MyBean
        MyBean myBean = context.getBean(MyBean.class);
        myBean.doSomething(); // 调用 MyBean.doSomething() 方法
    }

    @Bean
    public MyBean myBean(){
        return new MyBean();
    }
}

Preste atención a la siguiente visualización en la devolución específica.

 (2) preprocesamiento de AOP

Puede realizar un preprocesamiento relacionado con AOP en el Bean después de crear una instancia del Bean y antes de la inicialización implementando la interfaz BeanPostProcessor. Por ejemplo, puede generar dinámicamente un objeto proxy para Bean en el método postProcessBeforeInitialization de BeanPostProcessor para implementar funciones orientadas a aspectos AOP.

Enlaces de referencia:

1. Serie práctica de primavera (3): el uso mágico de BeanPostProcessor_Blog-CSDN de Qinghong Piaoyu

Supongo que te gusta

Origin blog.csdn.net/xiaofeng10330111/article/details/130190804
Recomendado
Clasificación