我报名参加金石计划1期挑战——分割10万奖池,这是我的第1篇文章,点击查看活动概况
Java 中的公共类称之为 Bean 或 Java Bean,而 Spring 中的 Bean 指的是将方针的生命周期,交个 Spring IoC 容器来处理的方针。所以 Spring 中的 Bean 方针在运用时,无需经过 new 来创建方针,只需求经过 DI(依托注入),从 Spring 中取出要运用的方针即可。 那么 Spring 中,Bean 的生命周期又有哪些呢?接下来,我们一起来看。
1.Bean 生命周期
Spring 中 Bean 的生命周期是指:Bean 在 Spring(IoC)中从创建到销毁的整个进程。 Spring 中 Bean 的生命周期首要包括以下 5 部分:
- 实例化:为 Bean 分配内存空间;
- 设置特色:将其时类依托的 Bean 特色,进行注入和装置;
- 初始化:
- 实行各种告知;
- 实行初始化的前置方法;
- 实行初始化方法;
- 实行初始化的后置方法。
- 运用 Bean:在程序中运用 Bean 方针;
- 销毁 Bean:将 Bean 方针进行销毁操作。
以上生命周期中,需求留意的是:“实例化”和“初始化”是两个彻底不同的进程,千万不要搞混,实例化仅仅给 Bean 分配了内存空间,而初始化则是将程序的实行权,从系统等级转换到用户等级,并初步实行用户添加的事务代码。
2.代码演示
接下来我们运用代码的方法在 Spring Boot 中,给我们演示一下 Bean 的生命周期。
PS:因为 Spring Boot 是根据 Spring 创建的,所以 Bean 在 Spring 或 Spring Boot 中的行为都是共同的,而 Spring Boot 又是现在主流的结构,所以本文运用 Spring Boot 来演示 Bean 的生命周期。
首先,我们创建一个 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 {
public void setBeanName(String s) {
System.out.println("实行 BeanName 的告知方法");
}
@PostConstruct
public void postConstruct() {
System.out.println("实行初始化方法");
}
public void use() {
System.out.println("运用 Bean");
}
@PreDestroy
public void preDestroy() {
System.out.println("实行销毁方法");
}
}
然后,我们再创建一个 MyBeanPostProcessor 类(类命无所谓,可随意指定),来完结初始化的前置方法和初始化的后置方法,具体完结代码如下:
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 {
if (beanName.equals("beanLifeComponent")) {
System.out.println("实行初始化前置方法");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("beanLifeComponent")) {
System.out.println("实行初始化后置方法");
}
return bean;
}
}
为什么要创建一个独自的类来实行初始化的前置方法和初始化的后置方法呢? 这是因为初始化的前置方法和后置方法是为一切 Bean 服务的,而非为某一个 Bean 服务的,所以这两个方法不能写在某个具体的 Bean 中,否则(这两个方法)不会实行。 最终,在 Spring Boot 的发起类中获取 Bean,具体完结代码如下:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// 得到上下文方针,并发起 Spring Boot 项目
ConfigurableApplicationContext context =
SpringApplication.run(DemoApplication.class, args);
// 获取 Bean
BeanLifeComponent component = context.getBean(BeanLifeComponent.class);
// 运用 Bean
component.use();
// 中止 Spring Boot 项目
context.close();
}
}
以上程序毕竟的实行结果如下图所示: 从上面的实行结果能够看出,代码实行次第契合 Bean 生命周期的实行次第:
- 实例化:为 Bean 分配内存空间;
- 设置特色:将其时类依托的 Bean 特色,进行注入和装置;
- 初始化:
- 实行各种告知;
- 实行初始化的前置方法;
- 实行初始化方法;
- 实行初始化的后置方法。
- 运用 Bean:在程序中运用 Bean 方针;
- 销毁 Bean:将 Bean 方针进行销毁操作。
那么问题来了,能不能先实行初始化再实行设置特色呢?也便是将生命周期中的过程 2 和过程 3 的实行次第交换一下? 答案是否定的。幻想一个场景,假设在初始化方法中要用到被注入方针的某个方法,比方以下代码:
@Controller
public class UserController {
@Resource
private UserService userService;
@PostConstruct // 初始化方法
public void postConstruct() {
userService.sayHi();
}
}
此刻假设先实行过程 2,先将 UserService 注入到其时类,再调用过程 3 实行初始化,那么程序的实行是正常的。然而假设将交互过程 2 和过程 3 的实行次第,那么程序实行就会报错(空指针反常),所以 Bean 的生命周期的次第有必要是:
1.实例化:为 Bean 分配内存空间; 2.设置特色:将其时类依托的 Bean 特色,进行注入和装置; 3.初始化:
- 实行各种告知;
- 实行初始化的前置方法;
- 实行初始化方法;
- 实行初始化的后置方法。 4.运用 Bean:在程序中运用 Bean 方针; 5.销毁 Bean:将 Bean 方针进行销毁操作。
总结
Bean 的生命周期指的是 Bean 在 Spring(IoC)中从创建到销毁的整个进程。Bean 的生命周期首要包括以下 5 个流程: 1.实例化:为 Bean 分配内存空间; 2.设置特色:将其时类依托的 Bean 特色,进行注入和装置; 3.初始化:
- 实行各种告知;
- 实行初始化的前置方法;
- 实行初始化方法;
- 实行初始化的后置方法。 4.运用 Bean:在程序中运用 Bean 方针; 5.销毁 Bean:将 Bean 方针进行销毁操作。
对错审之于己,毁誉听之于人,得失安之于数。
大众号:Java面试真题解析
面试合集:gitee.com/mydb/interv…