前言:
在面试中经常会被问到谈谈你对spring bean生命周期的理解,如果单方面的在网站看写的博客很难理解的,最好自己写代码体会他的实现流程。
1.先了解这几个类的意思
BeanNameAware:设置bean的名称类
BeanFactoryAware:bean工厂类接口
ApplicationContextAware:上下文类
InitializingBean :初始加载bean对象类
DisposableBean:bean对象销毁类
开始代码演示
1.创建项目工程
2.pom.xml依赖引入
<?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.itheima</groupId>
<artifactId>spring_consumer</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
3.applicationContext-user.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" xmlns:amp="http://activemq.apache.org/schema/core"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd">
<!-- spring bean生命周期执行流程
init-method="initMethod" :初始化方法
destroy-method="destroyMethod":销毁bean对象方法
-->
<bean id="userService" class="com.itheima.service.UserService" init-method="initMethod" destroy-method="destroyMethod"/>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
<bean id="userSerivceImpl" class="com.itheima.service.impl.UserSerivceImpl"/>
</beans>
4.编写UserService服务类
package com.itheima.service;
import java.util.Arrays;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.BeansException;
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;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class UserService implements BeanNameAware,
BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean{
// 对应<bean id="userService" />
public void setBeanName(String name) {
System.out.println("【步骤2】实现BeanNameAware接口,执行setBeanName方法,beanName值:userService");
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【步骤3】实现BeanFactoryAware接口,执行setBeanFactory()方法");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
String deanDefinitionNames = Arrays.toString(applicationContext.getBeanDefinitionNames());
System.out.println("【步骤4】实现ApplicationContextAware接口,执行setApplicationContext方法 调用deanDefinitionNames="+deanDefinitionNames);
}
//通过注解@PostConstruct自定义初始化方法
@PostConstruct
public void initPostConstruct(){
System.out.println("【步骤6】通过注解@PostConstruct自定义initPostConstruct()【初始化方法1】");
}
public void afterPropertiesSet() throws Exception {
System.out.println("【步骤7】实现InitializingBean初始化接口,执行afterPropertiesSe()方法执行【初始化方法2】");
}
//通过<bean>自定义init-method属性指定的初始化方法
public void initMethod() throws Exception {
System.out.println("【步骤8】执行spring配置文件bean标签的init-method属性【初始化方法2】");
}
//通过注解@PreDestroy自定义销毁方法
@PreDestroy
public void preDestroy(){
System.out.println("【步骤10】通过注解@PreDestroy自定义销毁方法preDestroy()【销毁方法1】");
}
//销毁bean对象
public void destroy() throws Exception {
System.out.println("【步骤11】实现DisposableBean接口的destroy()【销毁方法2】");
}
//通过<bean>自定义destroy-method属性指定的销毁方法
public void destroyMethod() throws Exception {
System.out.println("【步骤12】执行spring配置文件bean标签的destroy-method属性指定的【销毁方法3】");
}
}
5.编写UserServiceImpl实现类
package com.itheima.service.impl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class UserSerivceImpl implements BeanPostProcessor{
//Before前置初始化方法
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【步骤5】实现类UserSerivceImpl实现BeanPostProcessor接口,执行postProcessBeforeInitialization()前置方法");
return bean;
}
//After后置初始化方法
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("【步骤9】实现类UserSerivceImpl实现BeanPostProcessor接口,执行postProcessAfterInitialization()后置方法");
return bean;
}
}
6.编写测试类测试bean执行顺序
package com.itheima.service;
import org.apache.xbean.spring.context.ClassPathXmlApplicationContext;
public class TestBean {
public static void main(String[] args) {
/**
* 当程序加载运行时会根据spring中配置文件找到bean配置的属性和方法,
* 并通过java反射机制创建实例化bean对象;
*/
System.out.println("【步骤1】程序运行时,加载spring配置文件,实例化bean对象");
ClassPathXmlApplicationContext contetx =new ClassPathXmlApplicationContext("applicationContext-user.xml");
UserService user = contetx.getBean("userService",UserService.class);
contetx.close();
System.out.println("【步骤13】关闭spring bean容器contetx.close()");
}
}
7.输出结果
【步骤1】程序运行时,加载spring配置文件,实例化bean对象
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
【步骤2】实现BeanNameAware接口,执行setBeanName方法,beanName值:userService
【步骤3】实现BeanFactoryAware接口,执行setBeanFactory()方法
【步骤4】实现ApplicationContextAware接口,执行setApplicationContext方法 调用deanDefinitionNames=[userService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, userSerivceImpl]
【步骤5】实现类UserSerivceImpl实现BeanPostProcessor接口,执行postProcessBeforeInitialization()前置方法
【步骤6】通过注解@PostConstruct自定义initPostConstruct()【初始化方法1】
【步骤7】实现InitializingBean初始化接口,执行afterPropertiesSe()方法执行【初始化方法2】
【步骤8】执行spring配置文件bean标签的init-method属性【初始化方法2】
【步骤9】实现类UserSerivceImpl实现BeanPostProcessor接口,执行postProcessAfterInitialization()后置方法
【步骤10】通过注解@PreDestroy自定义销毁方法preDestroy()【销毁方法1】
【步骤11】实现DisposableBean接口的destroy()【销毁方法2】
【步骤12】执行spring配置文件bean标签的destroy-method属性指定的【销毁方法3】
【步骤13】关闭spring bean容器contetx.close()
8.在初始化阶段,有个特别重要的接口BeanPostProcessor,在初始化前、后调用
postProcessBeforeInitialization();//Before初始化前调用方法
postProcessAfterInitialization()//After初始化后调用方法
8.1实现流程图
9.初始化方式有三个,分别是
- InitializingBean类的afterPropertiesSet方法
- PostConstruct注解标注的方法
- spring配置文件applicationContext-user.xml的init-method="initMethod"
10.销毁方式有三个,分别是
- preDestroy注解标注的方法
- DisposableBean接口的destroy方法
- spring配置文件applicationContext-user.xml的配置的destroy-method=;"destroyMethod"
11.面试回答总结
1.根据程序加载运行输出结果回答:
【步骤1】程序运行时,加载spring配置文件,实例化bean对象
log4j:WARN No appenders could be found for logger (org.springframework.core.env.StandardEnvironment).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
【步骤2】实现BeanNameAware接口,执行setBeanName方法,beanName值:userService
【步骤3】实现BeanFactoryAware接口,执行setBeanFactory()方法
【步骤4】实现ApplicationContextAware接口,执行setApplicationContext方法 调用deanDefinitionNames=[userService, org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#0, userSerivceImpl]
【步骤5】实现类UserSerivceImpl实现BeanPostProcessor接口,执行postProcessBeforeInitialization()前置方法
【步骤6】通过注解@PostConstruct自定义initPostConstruct()【初始化方法1】
【步骤7】实现InitializingBean初始化接口,执行afterPropertiesSe()方法执行【初始化方法2】
【步骤8】执行spring配置文件bean标签的init-method属性【初始化方法2】
【步骤9】实现类UserSerivceImpl实现BeanPostProcessor接口,执行postProcessAfterInitialization()后置方法
【步骤10】通过注解@PreDestroy自定义销毁方法preDestroy()【销毁方法1】
【步骤11】实现DisposableBean接口的destroy()【销毁方法2】
【步骤12】执行spring配置文件bean标签的destroy-method属性指定的【销毁方法3】
【步骤13】关闭spring bean容器contetx.close()
面试回答:
1.当程序加载运行时会根据spring中配置文件找到bean配置的属性和方法,并通过java反射机制创建实例化bean对象。
Bean实现了BeanNameAware接口,执行了setBeanName方法,实现注入对象。
2.实现了BeanFactoryAware工厂接口,执行了setBeanFactory方法。
3.实现了ApplicationContext接口类,执行了setsetApplicationContest方法。
4.实现了BeanPostProcessor接口类,执行postProcessBeforeInitialization方法
5.实现了InitiliazingBean 执行afterPropertiesSet方法,并加载配置文件定义了init-method 则执行对应初始化方法BeanPostProcessor 执行postProcessorfterInitilization方法,完成 Bean的初始化,使得bean可以使用。
6.实现了DisposabileBean接口,加载配置文件中的destroy-method方法销毁bean对象实例。
简要回答:
- 程序加载时创建bean的实例化对象。
- 注入bean的相关实现接口管理bean对象。
- 初始化bean对象。
- 关闭并销毁bean实例化对象。
参考案例:https://blog.csdn.net/cool_summer_moon/article/details/106149339
写的有不足的地方欢迎同行评论提出观点,谢谢!!