谈谈Spring中Bean的生命周期?(让你瞬间通透~)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

1.Bean的生命周期

1.1、概括

1.2、图解

2、代码示例

2.1、初始化代码

2.2、初始化的前置方法和后置方法重写

2.3、Spring启动类

2.4、执行结果

2.5、经典面试问题

3.总结


1.Bean的生命周期


1.1、概括

Spring中Bean的生命周期就是Bean在Spring中从创建到销毁的整个过程主要分为以下5个部分

1.实例化给Bean分配内存空间对应JVM中的“加载”这里只是分配了内存

2.设置属性进行Bean的注入和装配

3.初始化

        a) 执行各种通知

        b) 执行初始化的前置工作

        c) 进行初始化工作使用注解 @PostConstruct 初始化 或者 使用xmlinit-method 初始化 前者技术比后者技术先进~

        d) 执行初始化的后置工作

4.使用Bean;

5.销毁Bean。

值得注意的是实例化和初始化是两个完全不同的过程前者只是给Bean分配内存空间而后者则是将程序执行权从系统级别转到用户级别执行用户添加的业务代码。

1.2、图解

下图以买房、盖房、入住、卖房为栗子方便理解~

2、代码示例


2.1、初始化代码

以下我将在Spring中演示Bean的生命周期

创建一个类名为BeanLifeComponent这个名字是自定义的 写下初始化的各类操作

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class BeanLifeComponent implements BeanNameAware {

    //执行各种通知
    @Override
    public void setBeanName(String s) {
        System.out.println("执行了通知");
    }

    //初始化的前置和后置方法不能写在这个Bean中

    //执行初始化方法(注解)
    @PostConstruct
    public void postConstruct() {
        System.out.println("通过注解 @PostConstruct 执行了初始化方法");
    }

    //使用
    public void useBean() {
        System.out.println("使用Bean");
    }

    //销毁
    @PreDestroy
    public void preDestory() {
        System.out.println("执行了销毁方法");
    }

}

注意1.这里不能写出实例化过程因为给Bean分配内存对应JVM类加载过程2.当前这个Bean中不能写初始化的前置方法和后置方法否则不会执行因为初始化的前置方法和后置方法是需要继承BeanPostProcessor接口重写两个方法实现的 并且是为所有 Bean 服务的而非为某一个 Bean 服务的若写在一个某一个Bean中则不会执行。

2.2、初始化的前置方法和后置方法重写

另外再创建一个类避免在一个Bean中自定义名为 MyBeanPostProcessor 接着继承BeanPostProcessor接口重写初始化的前置方法和后置方法如下代码

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

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行了初始化的前置方法");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行了初始化的后置方法");
        return bean;
    }
}

2.3、Spring启动类

最后在Spring启动类中获取Bean对象如下代码

import com.demo3.component.BeanLifeComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App3 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");

        //获取Bean
        BeanLifeComponent beanLifeComponent =
                context.getBean("beanLifeComponent", BeanLifeComponent.class);
        //使用Bean
        beanLifeComponent.useBean();
        //销毁Bean
        context.destroy();
    }
}

为什么这里不使用 ApplicationContext 而是使用它的子类 ClassPathXmlApplicationContext 呢因为 ClassPathXmlApplicationContext 中有destroy销毁方法用来销毁容器容器销毁了Bean自然就没了而ApplicationContext 中没有这个销毁方法演示的时候就体现不出来了。

2.4、执行结果

从执行结果来看符合咱们预期~

2.5、经典面试问题

        那么是否可以先执行 初始化 再执行 设置属性 呢 不可以想象一下如果在初始化的方法中要用你设置的属性就会引发空指针异常如下代码

@Controller
public class StudentController {

    //属性注入
    @Autowired
    private Student student;

    //初始化
    @PostConstruct
    public void init() {
        student.setName("周杰伦");
    }

}

如果你先执行了初始化 init() 方法而 init() 方法中需要使用属性注入后得到的Student对象那么此时还没有注入就进行修改就会引发空指针异常。
 

3.总结


Spring中Bean的生命周期就是Bean在Spring中从创建到销毁的整个过程。

主要就是由1.实例化、2.设置属性进行Bean的注入和装配、3.初始化、4.使用Bean、5.销毁Bean这五步构成并且任何顺序都不可以随意调换。

Bean的执行流程属于常见面试题一定要在理解的基础上牢记


 

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring