Spring6 当中 Bean 的生命周期的详细解析:有五步,有七步,有十步

1. Spring6 当中 Bean 的生命周期的详细解析:有五步,有七步,有十步

文章目录

  • 1. Spring6 当中 Bean 的生命周期的详细解析:有五步,有七步,有十步
  • 每博一文案
    • 1.1 什么是 Bean 的生命周期
    • 1.2 Bean 的生命周期 "五步"
    • 1.3 Bean 的生命周期 “七步”
    • 1.4 Bean 的生命周期 “十步”
  • 2. Bean的作用域不同,管理方式也将是不同的
    • 2.1 自己new的对象让Spring管理
  • 3. 总结:
  • 4. 最后:


每博一文案

“这个世界本来就是这样的,会认识形形色色的人,会遇到无法理解的恶意,
会感到失望,但是只要过去了,你就会发现,那些带着偏见自说自话的言论,
还有那些不能理解的恶意,都是在提醒我们不要成为那样的人。
或许会焦虑,会不知所措,生活也不太如意,会感到绝望。但我想说:前路漫漫,需自身强大。”

世界就是如此复杂,生活也从不是尽如人意,但我还是希望你,
即使见过那些肮脏与不堪,也依然能保有一颗温良的心。深渊可以凝视,但不要驻足。

只要心存光明,世界就不黑暗。

1.1 什么是 Bean 的生命周期

Spring 其实就是一个管理 Bean 对象的工厂。它负责对象的创建,对象的销毁等。

所谓的生命周期:简单的来说:就是一个对象从创建开始到最终销毁的整个过程。

  • 什么时候创建Bean 对象 ?
  • 创建 Bean 对象的前后会调用什么方法?
  • Bean 对象什么时候销毁?
  • Bean 对象的在销毁前后会调用生命方法?

那么我们为什么要知道 Bean 的生命周期呢?

其实生命周期的本质是:在哪个时间节点上调用了哪个类当中的哪个方法。

我们需要充分的了解在这个生命线当中,都有哪些特殊的时间节点。

只有我们知道了特殊的时间节点都在哪里了,这样我们才可以确定代码的对应上需要该写到哪里。

有时,我们可能需要在某个特殊的时间点上执行一段特定的代码,从而满足我们的需求,而这段代码可以放到哪个节点上,当生命线走到这里的时候,自然会被调用。

1.2 Bean 的生命周期 “五步”

关于 Bean 生命周期的管理,我们可以参考Spring的源码的:AbstractAutowireCapableBeanFactory类的doCreateBean()方法。 想要进一步了解该源码内容的大家可以移步至✏️✏️✏️Spring6 当中的 Bean 循环依赖的详细处理方案+源码解析-CSDN博客

这里的 Bean的生命周期“五步”是最基本,比较粗略的五步。

  1. 第一步:实例化 Bean
  2. 第二步:对 Bean 当中的属性进行赋值
  3. 第三步:初始化 Bean
  4. 第四步:使用 Bean
  5. 第五步:销毁 Bean

在这里插入图片描述

注意点:

  1. 其中的:第三步:初始化 Bean 需要我们通过在 spring.xml 配置文件当中的 标签当中通过 init-method= 属性指定初始化方法 是哪一个方法
  2. 其中的:第四步:销毁 Bean 也是需要我们通过在 spring.xml 配置文件当中的 标签当中的 destroy-method=性指定销毁方法 是哪个方法

实践测试:

准备工作:配置导入 相关的 spring 框架,让 Maven 帮我们导入 spring的相关jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.rainbowsea</groupId>
    <artifactId>spring6-006-bean-lifecycle-blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.11</version>
        </dependency>


        <!-- junit4 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

第一步: 定义一个 Bean 对象类,这里我们就定义一个 User 的类,来进行测试。

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.bean;

public class User {
    private String name;

    public User() {
        System.out.println(" 第一步: User 无参数构造方法调用");
    }


    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步: 为 User 这个 Bean 进行赋值操作");
    }


    /**
     * 这个方法需要自己写,方法名随意,但是注意写好之后,要通过init-method 配给Spring框架,让其知道这个东东
     */
    public void initUserBean() {
        System.out.println("第三步: 对 User Bean 对象进行一个初始化操作");
    }


    /**
     * 这个方法需要自己写,方法名随意,但是注意写好之后,要通过destroy-method配给Spring框架,让其知道这个东东
     */
    public void destroyUserBean() {
        System.out.println("第五步: 对 User Bean 对象进行一个销毁操作");
    }





    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

第二步: 配置相关的 spring.xml 告诉 Spring 框架要做的事情。

在这里插入图片描述

上面我们说到,注意点是:

  1. 其中的:第三步:初始化 Bean 需要我们通过在 spring.xml 配置文件当中的 标签当中通过 init-method= 属性指定初始化方法 是哪一个方法
  2. 其中的:第四步:销毁 Bean 也是需要我们通过在 spring.xml 配置文件当中的 标签当中的 destroy-method=性指定销毁方法 是哪个方法

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--init-method指明Bean的初始化方法是哪个;destroy-method指明Bean的销毁方法是哪个    -->
    <bean id="userBean" class="com.rainbowsea.bean.User" init-method="initUserBean" destroy-method="destroyUserBean">
        <property name="name" value="张三"></property> <!--set注入赋值-->
    </bean>
</beans>

第三步: 运行客户端,模拟测试

注意点:

我们需要手动调用 ClassPathXmlApplicationContext类下面的 close() 方法,正常关闭spring容器才会执行销毁方法。

在这里插入图片描述
在这里插入图片描述

package com.rainbowsea.test;

import com.rainbowsea.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleTest {

    @Test
    public void testRegisterBean() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("第四步: 使用 User Bean 对象" + userBean);

        ClassPathXmlApplicationContext classPathXmlApplicationContext = (ClassPathXmlApplicationContext) applicationContext;
        // 注意点:这里的 close()方法是,ClassPathXmlApplicationContext 类才有的,它的ApplicationContext 父类没有。
        // 父类无法调用子类特有的方法,所以这里我们需要强制类型转换回来(向下转型),为子类
        // 只有正常关闭spring容器才会执行销毁方法
        classPathXmlApplicationContext.close();


    }
}
 

执行结果:

在这里插入图片描述

总结注意点:

    1. 第一:配置文件中的init-method指定初始化方法。destroy-method指定销毁方法
    2. 第二:只有正常关闭spring容器,bean的销毁方法才会被调用。
    3. 第三:ClassPathXmlApplicationContext类才有close()方法。

1.3 Bean 的生命周期 “七步”

Bean 的生命周期分为“七步”: 是在五步的当中的:第三步初始化Bean 的前后添加上的,Bean 的后处理器。如果加上 Bean 后处理器的话,Bean 的生命周期就是 七步了。

具体七步如下:

  1. 第一步:实例化 Bean
  2. 第二步:对 Bean 当中的属性进行赋值
  3. 第三步:执行 Bean 后处理器的 befor() 方法执行,具体的是:postProcessBeforeInitialization(Object bean, String beanName) 方法
  4. 第四步:初始化 Bean
  5. 第五步:执行 Bean 后处理器的 after() 方法执行,具体的是 postProcessAfterInitialization(Object bean, String beanName) 方法
  6. 第六步:使用 Bean
  7. 第七步:销毁 Bean

在这里插入图片描述

第一步:关于 Bean 的后处理器的编写:

关于: bean的后处理器的编写:

编写 bean 后处理器,就是让一个类实现 implements BeanPostProcessor 接口类,同时并且重写其中的before(postProcessBeforeInitialization())和after(postProcessAfterInitialization())方法:

在这里插入图片描述
BeanPostProcessor 接口有,两个默认的方法,这两个方法,便是我们需要重写的,来实现我们自己的要的功能。

@Nullable
// 在 Bean 初始化之前被调用
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

@Nullable
// 在 Bean 初始化之后就被调用
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

其中两个参数的作用含义分别是:

在这里插入图片描述

    1. Object bean 是该对应的 bean 的对象
    2. String beanName 是该对应 bean 的在spring.xml配置文件当中 id的名字。

    在这里插入图片描述

这里我们定义一个MyBeanPostProcessor 类作为 Bean 后处理器 实现该 implements BeanPostProcessor 接口,并重写其中的两个默认方法。

在这里插入图片描述



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

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 该对应的 bean 的对象
        // String beanName 是该对应 bean 的在配置文件当中 id
        System.out.println("第三步:  Bean 初始化之前执行before()方法");

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 该对应的 bean 的对象
        // String beanName 是该对应 bean 的在配置文件当中 id
        System.out.println("第五步:  Bean 初始化之后执行after() 方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

第二步:将 Bean 后处理器配置到 spring.xml 文件当中去,告知 Spring 框架,同时进行管理。

在这里插入图片描述

大家需要注意的是:该配置Bean后处理器。这个后处理器将作用于当前整个配置文件中所有的bean。

在这里插入图片描述

也就是作用于当前这个名为 “spring6.xml” 文件当中的,所配置的所有 bean 都会自动使用上这个我们配置的 bean 后处理器。关于这一点具体说明。我们后面会详细说明的,大家放心。

第三步:模拟客户端,执行程序:

在这里插入图片描述


import com.rainbowsea.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleTest {

    @Test
    public void testRegisterBean() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring6.xml");
        User userBean = applicationContext.getBean("userBean", User.class);
        System.out.println("第六步: 使用 User Bean 对象" + userBean);

        ClassPathXmlApplicationContext classPathXmlApplicationContext = (ClassPathXmlApplicationContext) applicationContext;
        // 注意点:这里的 close()方法是,ClassPathXmlApplicationContext 类才有的,它的ApplicationContext 父类没有。
        // 父类无法调用子类特有的方法,所以这里我们需要强制类型转换回来(向下转型),为子类
        // 只有正常关闭spring容器才会执行销毁方法
        classPathXmlApplicationContext.close();


    }
}

上面我们提到了**“这个 bean 后处理器的是作用于整个对应的 spring.xml 的配置文件上的所有的 Bean”** 的关于这一点,我们下面进行一个简单的验证一下。

我们再创建一个空的类,然后进行一个构造方法的注入,交给 Spring 框架进行管理,是否还是会执行 Bean 处理器。

在这里插入图片描述
在这里插入图片描述

运行测试:在这里插入图片描述

从运行结果上看,我们可以明显的看出。这个Bean 后处理器是,作用于此 spring.xml 当中对应的整个 Bean 对象的 。简单的来说:就是只要你在某个其中的 spring.xml配置文件当中,启动了,并配置了对应的 Bean后处理器,那么整个 spring.xml 配置文件当中的所有的 Bean 对象都会自动启动上该 Bean 后处理器。

1.4 Bean 的生命周期 “十步”

Bean的生命周期的“十步”就是更加的细化了更加的灵活了

让我们一起来看一下,这所谓的十步,是在上面的七步当中的哪些节点当中,增加了那另外的三步。

十步是在下面这些位置,增加了另外的三步

  1. 首先在 Bean 后处理器的 befor ()执行的前后各自增加了一步,总共为两步
    1. Bean 后处理器的 befor()执行前,增加了 检查 Bean 是否实现了 Aware 的相关接口,并设置相关依赖。
    2. Bean 后处理器的 befor()执行后,增加了检查 Bean 是否实现了 InitializingBean 接口,并调用接口当中的方法
  2. 最后一步,添加在了 销毁 Bean 之前,增加了检查 Bean 是否实现了 DisposableBean 接口,并调用接口当中的方法。

具体十步如下:

  1. 第一步:实例化 Bean
  2. 第二步:对 Bean 当中的属性进行赋值
  3. 第三步: 检查 Bean 是否实现了 Aware 的相关接口,并设置相关依赖。
    1. 其中Aware 的相关接口有三个分别是:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
  4. 第四步:执行 Bean 后处理器的 befor() 方法执行,具体的是:postProcessBeforeInitialization(Object bean, String beanName) 方法
  5. 第五步:检查 Bean 是否实现了 InitializingBean 接口,并调用接口当中的方法
  6. 第六步:初始化 Bean
  7. 第七步:执行 Bean 后处理器的 after() 方法执行,具体的是 postProcessAfterInitialization(Object bean, String beanName) 方法
  8. 第八步:使用 Bean
  9. 第九步:检查 Bean 是否实现了 DisposableBean 接口,并调用接口当中的方法。
  10. 第十步:销毁 Bean

在这里插入图片描述

补充说明:

Aware相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

  • 当Bean实现了BeanNameAware,对应的方法是setBeanName(String name) :Spring会将Bean的名字传递给Bean。

  • 当Bean实现了BeanClassLoaderAware,对应的方法是setBeanClassLoader(ClassLoader classLoader) ; Spring会将加载该Bean的类加载器传递给Bean。

  • 当Bean实现了BeanFactoryAware,对应的方法是setBeanFactory(BeanFactory beanFactory); Spring会将Bean工厂对象传递给Bean。

  • 在这里插入图片描述
    InitializingBean 接口下对应的是:afterPropertiesSet () 方法。

  • 在这里插入图片描述
    DisposableBean 接口下的对应的是:destroy() 方法。

在这里插入图片描述

  • 测试以上10步,需要让User类实现5个接口,并实现其中的所有方法:

    • BeanNameAware

    • BeanClassLoaderAware

    • BeanFactoryAware

    • InitializingBean

    • DisposableBean

第一步:定义 Bean 类,我们还是使用这个 User 空白类,进行测试。

第二步:让 让User类实现5个接口(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,InitializingBean,DisposableBean),并实现其中的所有方法:

在这里插入图片描述

package com.rainbowsea.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {
    private String name;

    public User() {
        System.out.println("第一步: User 无参数构造方法调用");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("第五步:检查Bean是否实现了InitializingBean 接口,并调用接口方法.afterPropertiesSet执行");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("第九步: 检查 Bean是否实现了DisposableBean接口,并调用接口方法 destroy()  ");
    }
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("第三步:检查是否实现了Aware的相关接口并调用其中的实现接口方法(): Bean 这个类的加载器" + classLoader);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("第三步:检查是否实现了Aware的相关接口并调用其中的实现接口方法():  生产这个Bean的工厂对象是 " +beanFactory);
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("第三步:检查是否实现了Aware的相关接口并调用其中的实现接口方法():  这个Bean的名称是: " + name);
    }




    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("第二步: 为 User 这个 Bean 进行赋值操作");
    }


    /**
     * 这个方法需要自己写,方法名随意,但是注意写好之后,要通过init-method 配给Spring框架,让其知道这个东东
     */
    public void initUserBean() {
        System.out.println("第六步: 对 User Bean 对象进行一个初始化操作");
    }


    /**
     * 这个方法需要自己写,方法名随意,但是注意写好之后,要通过destroy-method配给Spring框架,让其知道这个东东
     */
    public void destroyUserBean() {
        System.out.println("第十步: 对 User Bean 对象进行一个销毁操作");
    }





    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }


}

配置的 spring.xml 文件信息不变:保持和生命周期“七步”是一样的,因为十步是基于七步的基础上细化,添加的。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。-->
    <bean class="com.rainbowsea.bean.MyBeanPostProcessor"/>

    <!--init-method指明Bean的初始化方法是哪个;destroy-method指明Bean的销毁方法是哪个    -->
    <bean id="userBean" class="com.rainbowsea.bean.User" init-method="initUserBean" destroy-method="destroyUserBean">
        <property name="name" value="张三"></property> <!--set注入赋值-->
    </bean>


</beans>

对应的 Bean 后处理也是不变的(和生命周期七步是一样的),因为十步是基于七步的基础上细化,添加的。

package com.rainbowsea.bean;

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

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 该对应的 bean 的对象
        // String beanName 是该对应 bean 的在配置文件当中 id
        System.out.println("第四步:  Bean 初始化之前执行before()方法");

        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // Object bean 是 该对应的 bean 的对象
        // String beanName 是该对应 bean 的在配置文件当中 id
        System.out.println("第七步:  Bean 初始化之后执行after() 方法");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

最后:运行测试:

在这里插入图片描述

2. Bean的作用域不同,管理方式也将是不同的

Spring 根据 Bean 的作用域来选择管理方式。

  1. 对于 singleton (spring 默认的单例)作用域的 Bean ,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成的,以及何时被销毁的,符合上述的生命周期的“五步”,“七步”,“十步” 的流程。
  2. 而对于 prototype(多例) 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给了客户端代码管理,Spring 容器将不再跟踪其生命周期。不符合上述的生命周期的“五步”,“七步”,“十步” 的流程。

如下:我们把上述的User类的“Bean 的生命周期“十步”演示法当中的 ”spring.xml文件中的配置scope设置为prototype。其他任何内容保持不变。进行演示

在这里插入图片描述

运行测试:

在这里插入图片描述

从运行结果上看:与之前的 bean 生命周期十步相比较看:我们可以明显的发现。Spring 仅仅到bean 创建后,就不再管理了。而是交给客户端进行自行管理了。spring 不再管理后面的操作了。

2.1 自己new的对象让Spring管理

有些时候可能会遇到这样的需求,某个java对象是我们自己new的,然后我们希望这个对象被Spring容器管理,怎么实现?

准备工作,我们首先创建一个 bean 对象,这里我们创建一个空的 Vip 类,作为 bean 。

在这里插入图片描述

我们需要通过 DefaultListableBeanFactory 这个对象,将我们 new 的对象交给 Spring 管理

再通过: DefaultListableBeanFactory 这个对象下的registerSingleton()方法,(这个交给 Spring 管理的bean的id/name 的命名,对于要交给spring管理的对象)
defaultListableBeanFactory.registerSingleton(“vipBean”,vip);

在这里插入图片描述

核心代码:

在这里插入图片描述

import com.rainbowsea.bean.User;
import com.rainbowsea.bean.Vip;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BeanLifecycleTest {

    @Test
    public void test() {
        // 第一步: 我们自己 new 一个对象,方便交给 spring 管理
        Vip vip = new Vip();
        System.out.println(vip);  // 打印一下地址,方便比较


        //  第二步:将以上自己 new 的这个对象纳入 Spring 框架容器当中去管理,半路上交给 Spring来管理
        //  通过 DefaultListableBeanFactory 这个对象,将我们 new 的对象交给 Spring 管理
        DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
        // 通过: registerSingleton()方法,(这个交给 Spring 管理的bean的id/name 的命名,对于要交给spring管理的对象)
        
        defaultListableBeanFactory.registerSingleton("vipBean",vip);

        // 从Spring 容器中获取:通过上述我们 registerSingleton()方法中定义的id,进行一个获取
        Object vipBean = defaultListableBeanFactory.getBean("vipBean");
        System.out.println(vipBean);
        // 单例:地址是一样的。

    }
}

我们是自己new 的对象,半路上交给 Spring 框架进行管理的,所以我们不需要配置spring.xml 的文件上配置相关的 bean 信息。

运行结果:

在这里插入图片描述

3. 总结:

  1. 熟悉Bean 的生命周期,各个时间节点上所能做的事情,可以让我们更加灵活的掌握Spring上的运用,更加的灵活,实现我们的业务需要。
  2. Bean 的生命周期 “五步”;注意点:初始化 Bean 需要我们通过在 spring.xml 配置文件当中的 标签当中通过 init-method= 属性指定初始化方法 是哪一个方法;销毁 Bean 也是需要我们通过在 spring.xml 配置文件当中的 标签当中的 destroy-method=性指定销毁方法 是哪个方法
  3. Bean 的生命周期分为“七步”;是在五步的当中的:第三步初始化Bean 的前后添加上的,Bean 的后处理器。如果加上 Bean 后处理器的话,Bean 的生命周期就是 七步了。该配置Bean后处理器。这个后处理器将作用于当前整个配置文件中所有的bean。
  4. Bean 的生命周期 “十步”;需要让类实现5个接口(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware,InitializingBean,DisposableBean),并实现其中的所有方法:
  5. singleton (spring 默认的单例)作用域的 Bean ,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成的,以及何时被销毁的,符合上述的生命周期的“五步”,“七步”,“十步” 的流程。
  6. Bean的作用域不同,管理方式也将是不同的;而对于 prototype(多例) 作用域的 Bean,Spring 只负责创建,不符合上述的生命周期的“五步”,“七步”,“十步” 的流程。 singleton (spring 默认的单例)作用域的 Bean 符合上述的生命周期的“五步”,“七步”,“十步” 的流程。
  7. 自己new的对象让Spring管理(将以上自己 new 的这个对象纳入 Spring 框架容器当中去管理,半路上交给 Spring来管理);通过: DefaultListableBeanFactory 这个对象下的registerSingleton()方法,(这个交给 Spring 管理的bean的id/name 的命名,对于要交给spring管理的对象)

4. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/585630.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ThinkPHP Lang多语言本地文件包含漏洞(QVD-2022-46174)漏洞复现

1 漏洞描述 ThinkPHP是一个在中国使用较多的PHP框架。在其6.0.13版本及以前&#xff0c;存在一处本地文件包含漏洞。当ThinkPHP开启了多语言功能时&#xff0c;攻击者可以通过lang参数和目录穿越实现文件包含&#xff0c;当存在其他扩展模块如 pear 扩展时&#xff0c;攻击者可…

esp32学习

开启自动补全功能 Arduino IDE 2.0开启代码补全及修改中文_arduino ide怎么设置中文-CSDN博客 PWM 、 ADC转换 在使用这个adc默认配置的时候adc引脚的输入电压必须是介于0-1之间&#xff0c;如何高于1v的电压都会视为一个最高值&#xff0c;如果要增加测量电压你就需要配置一…

【JAVA】part5-Java集合

Java 集合 Java集合概述 Java数组的局限性 数组初始化后大小不可变&#xff1b;数组只能按索引顺序存取。 Java的java.util包主要提供了以下三种类型的集合&#xff1a; List&#xff1a;一种有序列表的集合&#xff0c;例如&#xff0c;按索引排列的Student的List&#xff1b…

车载气象站:可移动监测的气象站

TH-CZ5车载气象站是一种专门针对车辆、船舶等应急环境检测设备而设计的可移动监测的气象站。 一、系统介绍 车载气象站系统采用先进的高精度GPS及三轴电子罗盘&#xff0c;可实现车行驶时的风速、风向检测。整机为野外型设计&#xff0c;同时还可对气温、相对湿度、雨量、气压…

Linux修改文件权限命令 chmod

【例子引入】 以下面命令为例&#xff1a; chmod 777 Random.py 当写入下面名为Random.py的代码后&#xff1a; 如果直接运行&#xff0c;会显示权限不够 当输入 chmod 777 Random.py 更改权限后&#xff0c;才能够正常运行 在终端中输入 这条命令是关于Linux或Unix-like系…

FlaUI

FlaUI是一个基于微软UIAutomation技术&#xff08;简称UIA&#xff09;的.NET库&#xff0c;它主要用于对Windows应用程序&#xff08;如Win32、WinForms、WPF、Store Apps等&#xff09;进行自动化UI测试。FlaUI的前身是TestStack.White&#xff0c;由Roemer开发&#xff0c;旨…

Socket编程--TCP连接以及并发处理

流程图 网络传输流程&#xff1a; TCP连接&#xff1a; api 客户端&#xff1a; socket: 创建套接字 domain: AF_INET &#xff1a;IPv4 type: SOCK_STREAM(tcp)、SOCK_DGRAM&#xff08;udp&#xff09; protocol: 0 默认协议 返回值&#xff1a;成功返回一个新的套接字…

Linux-进程间通信(进程间通信介绍、匿名管道原理及代码使用、命名管道原理及代码使用)

一、进程通信介绍 1.1进程间通信的目的 数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程资源共享&#xff1a;多个进程之间共享同样的资源。通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它们&#xff09;发生了某…

值得买科技新思路,导购电商的终点是“AI+出海”?

在以往&#xff0c;大众普遍认为品牌的消费者大多是高度忠诚人群&#xff0c;而事实上&#xff0c;非品牌忠诚者相比重度消费者&#xff0c;对促进品牌增长更为重要。 这类非品牌忠诚者被定义为摇摆的消费者群体&#xff0c;也就是那些购买品牌产品概率在20%-80%之间的消费者。…

【Unity动画系统】Animator组件的属性

介绍Animator组件的全部属性 Controller&#xff1a;动画控制器 Avatar&#xff1a;人物骨骼 Apply Root Motion&#xff1a;有一些动画片段自带位移&#xff0c;如果希望自带的位移应用在游戏对象上&#xff0c;那么就勾选&#xff1b;如果自己编写脚本&#xff0c;那么就不…

如何用智能获客开启新商机?揭秘赢销侠软件的奇效

在当今数字化竞争日益激烈的商业环境中&#xff0c;企业为了生存和发展&#xff0c;必须寻找新的途径以获取潜在客户。智能获客作为一种新型的营销方式&#xff0c;正以其高效、精准的特点改变着传统的市场开拓模式。而在这个过程中&#xff0c;自动获客软件的作用愈发凸显&…

LLM大语言模型原理、发展历程、训练方法、应用场景和未来趋势

LLM&#xff0c;全称Large Language Model&#xff0c;即大型语言模型。LLM是一种强大的人工智能算法&#xff0c;它通过训练大量文本数据&#xff0c;学习语言的语法、语义和上下文信息&#xff0c;从而能够对自然语言文本进行建模。这种模型在自然语言处理&#xff08;NLP&am…

杰发科技AC7840——SPI通信简介(1)_跑通Demo

0. 简介 一些配置项&#xff1a; CPHA&#xff1a;相序 CPLO&#xff1a;极性 看着demo需要按键&#xff0c;于是去掉按键&#xff0c;去掉打印&#xff0c;直接输出波形看逻辑分析仪的信号。 其实现在做这些demo测试应该都有逻辑分析仪&#xff0c;直接看波形更直观一点。…

分享:抖音老阳口中的选品师项目好做吗?

近年来&#xff0c;随着抖音等短视频平台的兴起&#xff0c;越来越多的博主通过分享自己的生活、知识和见解吸引了大量粉丝。其中&#xff0c;抖音博主老阳以其独特的选品眼光和专业的产品评测&#xff0c;在广大网友中树立了良好的口碑。那么&#xff0c;老阳口中的选品师项目…

【MySQL】MVCC的实现原理

【MySQL】MVCC的实现原理 MVCC简介事务的隔离级别读未提交&#xff08;Read Uncommitted&#xff09;概念分析 读已提交&#xff08;Read Committed&#xff09;概念分析结论 可重复读&#xff08;Repeatable Read&#xff09;概念分析结论 串行化&#xff08;Serializable &am…

实战—登录功能引发的逻辑漏洞

密码找回功能可能存在的漏洞 1.验证码发送后前端返回 2.验证码无次数限制可爆破 3.验证码可控/邮箱篡改为自己的接收短信验证码/手机号码篡改为自己的接收短信验证码 4.越权漏洞—>自己验证码通过改包然后修改他们密码 5.任意用户密码重置 6.密保问题在前端源码 实战…

Linux基础——Linux开发工具(上)_vim

前言&#xff1a;在了解完Linux基本指令和Linux权限后&#xff0c;我们有了足够了能力来学习后面的内容&#xff0c;但是在真正进入Linux之前&#xff0c;我们还得要学会使用Linux中的几个开发工具。而我们主要介绍的是以下几个&#xff1a; yum, vim, gcc / g, gdb, make / ma…

49. 字母异位词分组 128. 最长连续序列

49. 字母异位词分组 128. 最长连续序列 把集合里面的所有元素都放入set容器里面 定义结果最大连续数量 ans for循环遍历每个元素 先判断集合里面有没有比这个元素小1的 如果没有 说明这个元素就是序列的第一个元素 然后接着找集合里面有没有比这个元素大1的 while一直找 …

牛客NC353 回文子串的数量【中等 字符串,枚举,回文 C++/Java/Go/PHP 高频】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/3e8b48c812864b0eabba0b8b25867738 思路 参考答案C class Solution {public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可*** param str string字符串…

详解centos8 搭建使用Tor 创建匿名服务和匿名网站(.onion)

1 Tor运行原理&#xff1a; 请求方需要使用&#xff1a;洋葱浏览器&#xff08;Tor Browser&#xff09;或者Google浏览器来对暗&#xff0c;网网站进行访问 响应放需要使用&#xff1a;Tor协议的的Hidden_service 2 好戏来了 搭建步骤&#xff1a; 1.更新yum源 rpm -Uvh h…