[Primavera] Análisis del proceso de ejecución: comprender el alcance y el ciclo de vida de los beans

 Hola, hola a todos ~ Soy tu viejo amigo: protege a Xiao Zhou ღ  


Lo que les traigo hoy es el análisis del proceso de ejecución del proyecto Spring  y los seis alcances y ciclos de vida del objeto Bean , este artículo se los explicaré, echemos un vistazo~


Este problema está incluido en la columna del blogger : JavaEE_Protect Xiao Zhouღ's Blog-CSDN Blog

Adecuado para principiantes en programación, los amigos interesados ​​pueden suscribirse para ver otros "Conceptos básicos de JavaEE".

Estén atentos para más aspectos destacados: Proteger Xiaozhou ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★*'


1. Proceso de ejecución de primavera 

Proceso de ejecución de Bean (proceso de ejecución de Spring) : inicie el contenedor de Spring -> lea el archivo de configuración de Spring -> cree una instancia del objeto Bean (asignar espacio de memoria, desde cero) -> registre el Bean en Spring (operación de guardado) -> guarde el Bean Inyectar en la clase requerida (operación de búsqueda).

 Aquellos que estén interesados ​​en las operaciones relacionadas con las anotaciones de Spring pueden leer otro blog del blogger:

[Spring] Usar anotaciones para leer y almacenar objetos Bean_Proteger el blog de Xiao Zhouღ-CSDN Blog


En segundo lugar, el alcance del bean

Spring es un contenedor IoC que contiene muchas herramientas y métodos.También se puede considerar que Spring se usa para leer y almacenar objetos Bean, por lo que los objetos Bean tienen un papel crucial en Spring.

2.1 Observar el alcance predeterminado del objeto Bean en Spring a través de un caso

Diseñe un objeto Bean público de la clase Student, regístrelo en el contenedor Spring y entrégueselo a los usuarios A y B. El usuario A modifica silenciosamente los datos del objeto Bean del tipo Student sin ninguna moral. Cuando el usuario B usa el Bean objeto Es bastante molesto encontrar que los datos han sido manipulados~

La clase Student es la siguiente:

@Data
public class Student {
    private int id; // 学号
    private String name; // 姓名
    private int age; // 年龄
    private String sex; // 性别
}

Permítanme presentarles un marco de trabajo de terceros:  lombok 

"Lombok" es un marco de código abierto que se usa muy comúnmente en el desarrollo de Java. Su objetivo es simplificar el proceso de desarrollo mediante la generación automática de código repetitivo para código Java, reducir el código redundante y mejorar la legibilidad del código.

Lombok proporciona una serie de anotaciones, como @Data, @Getter, @Setter, @NoArgsConstructor, etc. Al agregar estas anotaciones a la clase, se pueden generar automáticamente los métodos getter, setter, constructor y otros métodos correspondientes. Esto puede simplificar enormemente la escritura de clases Java y mejorar la eficiencia del desarrollo .

Para usar Lombok, debe agregar dependencias de Lombok al proyecto e instalar el complemento de Lombok en el IDE para que las anotaciones de Lombok se puedan procesar correctamente al compilar y ejecutar.

 Lombox depende de:

 <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
      <scope>provided</scope>
 </dependency>

Los blogueros usan anotaciones @Data de lombox, @Data contiene anotaciones @Setter y @Getter, es decir, crean automáticamente métodos set y get para la clase Student.


Objeto Public Bean, inyectado en Spring:

@Component
public class Users {
    //使用方法注解将 学生张三注入到 Spring 中
    @Bean
    public Student getStu() {
        Student stu = new Student();
        stu.setId(123456);
        stu.setName("张三");
        stu.setAge(18);
        stu.setSex("男");
        return stu;
    }
}

El usuario A obtiene el objeto stu Bean de Spring y lo modifica:

@Controller
public class UserA {

    //从Spring 中获取Bean 对象
    @Resource //@Autowired
    private Student stu;

    public Student getStu() {
        System.out.println("用户A获取原Bean对象"+ '\n'+ stu.toString());

        //对原Bean 的数据进行修改
        stu.setName("李四");
        stu.setSex("女");
        return stu;
    }
}

El usuario B obtiene el objeto stu Bean de Spring y lo usa (imprime):

@Controller
public class UserB {
    //从Spring 中获取Bean 对象
    @Resource //@Autowired
    private Student stu;

    public Student getStu() {
        System.out.println("用户B获取被用户A修改过的 Bean :" + '\n' + stu.toString());
        return stu;
    }
}

Obtenga los objetos del usuario A y del usuario B en la clase de inicio, llame al método getStu() y obtenga el objeto stu Bean:

public class App {
    public static void main(String[] args) {
        //1. 获取Spring 上下文对象,里面管理着 bean 对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        //2. 获取指定的 Bean 对象
        UserA userA = context.getBean("userA", UserA.class);
        Student stuA = userA.getStu();
        System.out.println("用户A:" + stuA.toString());


        UserB userB = context.getBean("userB", UserB.class);
        Student stuB = userB.getStu();
        System.out.println("用户B:"+ stuB.toString());
    }
}


analisis de CASO:

El motivo de los resultados de ejecución de las operaciones anteriores es que Bean es un modo singleton por defecto (singleton: una clase tiene solo una instancia), es decir, el usuario A y el usuario B operan en el mismo objeto Bean, por lo que el usuario A modifica el único Bean, el Bean obtenido por el usuario B es el modificado.

El alcance del Bean in Spring por defecto es el modo singleton singleton~


2.2 6 alcances de los objetos Bean

Limitar el alcance disponible de variables en un programa se llama alcance. El alcance de un objeto Bean se refiere a un cierto patrón de comportamiento en todo el ciclo de vida de Spring. Por ejemplo: alcance singleton (singleton) significa que solo hay una copia en el Las instancias completas de Spring se comparten globalmente. Cuando otras personas modifican la única instancia, la instancia obtenida por otra persona será el valor modificado.

El marco Spring proporciona varias opciones de alcance para los objetos Bean. Los siguientes son los seis ámbitos de objeto de frijol comunes en el marco de Spring:

  1. Singleton (caso único) : solo hay una instancia de Bean en toda la aplicación. Cada solicitud devolverá la misma instancia. Obtener Bean (adquirido a través de applicationContext.getBean, etc.), ensamblar Bean (es decir, a través de @Autowired, @Resource)

  2. Prototype (prototipo) : Cada solicitud creará una nueva instancia de Bean. Cada solicitud devuelve una instancia diferente. Obtener Bean (adquirido a través de applicationContext.getBean, etc.), ensamblar Bean (es decir, a través de @Autowired, @Resource)

  3. Request (solicitud) : En cada solicitud HTTP, se creará una nueva instancia de Bean. Cada solicitud HTTP devuelve una instancia diferente.

  4. Sesión (session ) : Durante la sesión del usuario, se creará una nueva instancia de Bean. Para solicitudes posteriores del mismo usuario, se devolverá la misma instancia.

  5. Sesión Global ( sesión global ) : Durante la sesión global de toda la aplicación, se creará una nueva instancia de Bean. Para solicitudes posteriores de la misma sesión global, se devolverá la misma instancia.

  6. Aplicación ( Application ) : Durante el ciclo de vida de toda la aplicación Web, se creará una nueva instancia de Bean. Cada aplicación web devuelve la misma instancia.

Nota: El uso del alcance depende de los requisitos y escenarios de aplicación específicos. El marco Spring también admite ámbitos personalizados. Los proyectos Spring ordinarios solo admiten singleton (caso único) y prototipo (casos múltiples). Los 4 estados restantes se pueden configurar en el proyecto SpringMVC.


2.3 Establecer el alcance del objeto Bean

El uso de la etiqueta @Scope se puede usar para declarar el alcance del Bean, como se muestra en el siguiente código:

@Component
public class Users {
    //声明为多例模式,每此请求都会实例一个新的Bean对象
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
    //使用方法注解将 学生张三注入到 Spring 中
    @Bean(name = "stu") //给 Bean 对象起一个名字
    public Student getStu() {
        Student stu = new Student();
        stu.setId(123456);
        stu.setName("张三");
        stu.setAge(18);
        stu.setSex("男");
        return stu;
    }
}

La etiqueta @Scope puede modificar tanto métodos como clases. Este es el método de modificación. Hay dos formas de configurar @Scope:

1. Establezca el valor directamente: @Scope("prototipo")

Los amigos que son buenos en inglés pueden memorizar las palabras directamente, lo cual es bastante directo y conveniente ~

2. Utilice la configuración de enumeración: @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

En este punto, hemos establecido un modo de múltiples instancias para el objeto Bean de tipo Estudiante en el ejemplo anterior, y lo ejecutamos en este momento para ver:


3. Ciclo de vida del frijol

El llamado ciclo de vida de Bean (objeto) se refiere a todo el proceso desde la creación hasta la destrucción de un objeto ordinario, y llamamos a todo el proceso el ciclo de vida del objeto. El objeto Bean también es un objeto de instancia ordinario.

El ciclo de vida de un objeto Bean se divide en las siguientes cinco partes:

1. Instanciación: Bean (asignar espacio de memoria (área de montón) para objetos Bean)

2. Establecer propiedades : después de la creación de instancias, el contenedor inyectará los valores de propiedad configurados o las referencias en el objeto Bean, lo que se puede hacer a través del constructor, el método setter o la inyección de campo.

3. Inicialización del objeto Bean: el proceso de inicialización del objeto Bean generalmente incluye los siguientes pasos:

  • Cargando la definición del bean: Primero, el contenedor leerá el archivo de configuración o escaneará las anotaciones para obtener la información de definición del bean y almacenarla en la memoria.

  • Crear una instancia de Bean: De acuerdo con la información de definición del Bean, el contenedor instanciará el objeto Bean. Esto se puede hacer llamando al constructor predeterminado o usando métodos de fábrica, etc.

  • Inyectar dependencias: una vez que se crea la instancia de Bean, el contenedor verifica las dependencias declaradas en la definición de Bean e inyecta las dependencias correspondientes en la instancia de Bean. La inyección de dependencia se puede lograr a través del constructor, el método setter o la inyección de campo.

  • Implemente la interfaz Aware: si el Bean implementa una interfaz Aware específica (como BeanNameAware, BeanFactoryAware, etc.), el contenedor llamará al método de devolución de llamada correspondiente para proporcionar información adicional sobre el contenedor.

  • Procesamiento antes de la inicialización del Bean: antes de que se inicialice la instancia del Bean, el contenedor llamará al método postProcessBeforeInitialization() de la clase de implementación de la interfaz BeanPostProcessor, lo que permitirá a los desarrolladores realizar un procesamiento lógico personalizado antes de la inicialización.

  • Inicializar Bean: después de que se complete el proceso de creación de instancias, el contenedor llamará al método de inicialización de acuerdo con la configuración en la definición de Bean. Esto se puede hacer anotando la clase Bean con la anotación @PostConstruct o implementando el método afterPropertiesSet() de la interfaz InitializingBean.

  • Procesamiento después de la inicialización del Bean: después de inicializar la instancia del Bean, el contenedor volverá a llamar al método postProcessAfterInitialization() de la clase de implementación de la interfaz BeanPostProcessor, lo que permitirá a los desarrolladores realizar un procesamiento lógico personalizado después de la inicialización.

  • Inicialización completa de Bean: en este punto, el proceso de inicialización de Bean está completo y se puede agregar al contenedor para que otros Beans realicen la inyección de dependencia u otras operaciones.

Cabe señalar que lo anterior es un proceso típico de inicialización de objetos Bean, y puede haber algunas diferencias en las aplicaciones reales, por ejemplo, el uso de proxies, herencia de clases padre, etc., causará diferencias en el proceso de inicialización. Al mismo tiempo, las diferentes implementaciones de contenedores pueden tener algunas diferencias sutiles.

4. Use Bean: el objeto Bean es un objeto instanciado ordinario, el uso es el mismo, vea cómo se diseña la clase

5. Destruye el frijol:

La destrucción de objetos Bean se puede lograr de las siguientes maneras:

  • Use el método Destroy: puede implementar la interfaz de DisabledBean en la clase Bean y anular el método destroy(). Cuando el contenedor destruya la instancia de Bean, llamará automáticamente a este método para destruir el objeto Bean.
public class MyBean implements DisposableBean {
    // ...
    
    @Override
    public void destroy() {
        // 销毁操作
        // ...
    }
}

  • Use la anotación @PreDestroy: puede agregar la anotación @PreDestroy al método de destrucción de la clase Bean. Cuando el contenedor destruya la instancia de Bean, el método marcado con la anotación se activará para realizar la operación de destrucción.
public class MyBean {

    // ...
    
    @PreDestroy
    public void destroy() {
        // 销毁操作
        // ...
    }
}

  • Configure el método de destrucción: en el archivo de configuración (como el archivo de configuración XML), puede especificar el método llamado cuando se destruye el Bean especificando el atributo destroy-method. Este método puede ser cualquier método público de la clase Bean.
<bean id="myBean" class="com.example.MyBean" destroy-method="destroy">
    <!-- ... -->
</bean>

Cabe señalar que el tiempo de destrucción del objeto Bean lo administra el contenedor, lo que generalmente ocurre cuando el contenedor está cerrado. Si se trata de un bean singleton, la operación de destrucción se desencadena cuando se cierra el contenedor o se llama manualmente al método de destrucción. Si es un prototipo o un bean con ámbito de sesión (ámbito de sesión), debe destruirse manualmente.


Diagrama de flujo de ejecución:


La diferencia entre instanciación e inicialización:

Los "eventos" del sistema de nivel Java durante la creación de instancias y la configuración de propiedades, el proceso de operación no puede ser intervenido por humanos, mientras que la inicialización se proporciona para los desarrolladores, y el procesamiento de "eventos" personalizados se puede realizar después de la creación de instancias y antes de que se complete la carga de la clase.

En general, la creación de instancias es el proceso de creación de una instancia de Bean, mientras que la inicialización es el proceso de asignación de propiedades y la invocación del método de devolución de llamada en el objeto Bean creado. La creación de instancias es el paso básico para crear un objeto Bean, y la inicialización es un paso importante para configurar y preparar el objeto Bean después de crear la instancia.


Da un ejemplo para describir vívidamente el ciclo de vida del objeto Bean: comprar una casa

1. Instanciación: se construyó una casa en bruto en cierta ciudad (empezando desde cero, convirtiendo bytecodes en objetos en la memoria, simplemente asignando memoria)

2. Establecer propiedades: (el contenedor inyectará los valores de propiedad configurados o referencias en el objeto Bean). Compra materiales de decoración e introduce recursos externos.

3. Inicialización: Decora la casa~

  • Notificaciones varias: contactar con varios maestros de decoración, fontaneros, electricistas, albañiles...
  • Trabajo previo para la inicialización: el maestro de decoración inspecciona el entorno de la casa en bruto en el sitio y formula un plan de decoración.
  • Llevar a cabo el trabajo de inicialización: (@PostConstruct initialization, init-method initialization), los maestros de decoración llevan a cabo la decoración, algunos de ellos tienen buenas habilidades de decoración y otros tienen habilidades de decoración deficientes.
  • Trabajo posterior inicial: Limpiar la casa después de completar la renovación.

4. Usa el objeto Bean: Check in with bags~

5. Destruye el objeto Bean: demuele o vende esta casa~

Asegúrese de configurar primero la propiedad y luego realice la operación de inicialización.


Bueno, aquí vamos, [Spring] Análisis del proceso de ejecución: comprender el alcance y el ciclo de vida del Bean  Los bloggers han compartido su contenido y espero que sea útil para todos. Si hay algo mal, bienvenido a criticar y corregir. 

Vista previa del próximo número: marco [SpringBoot] ~

Gracias a todos los que leyeron este artículo, y se avecinan más eventos emocionantes: Proteger Xiaozhou ღ *★,°*:.☆( ̄▽ ̄)/$:*.°★* 

Cuando te conocí, todas las estrellas cayeron sobre mi cabeza ...

Supongo que te gusta

Origin blog.csdn.net/weixin_67603503/article/details/131284480
Recomendado
Clasificación