当前位置:   article > 正文

大厂高频面试题Spring Bean生命周期最详解,字节跳动面试问题及答案java_springbean生命周期面试

springbean生命周期面试

3.编写测试类BeanLifeCycleTest,具体代码如下:

package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

@Slf4j

public class BeanLifeCycleTest {

public static void main(String[] args) {

log.info(“====== 开始初始化Spring容器 ========”);

ApplicationContext factory = new ClassPathXmlApplicationContext(“application-beans.xml”);

log.info(“====== 初始化Spring容器成功 ========”);

//获取Author实例

Author author = factory.getBean(“author”, Author.class);

log.info(author.toString());

log.info(“====== 开始销毁Spring容器 ========”);

((ClassPathXmlApplicationContext) factory).registerShutdownHook();

}

}

4.运行结果

运行结果如下:

15:49:12.477 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 调用BeanPostProcessor实现类构造器!!

15:49:12.494 [main] INFO com.tom.lifecycle.Author - 【构造器】调用Tom类的构造器实例化

15:49:12.527 [main] INFO com.tom.lifecycle.Author - 【注入属性】address

15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【注入属性】age

15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【注入属性】name

15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【BeanNameAware接口】调用setBeanName方法

15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【BeanFactoryAware接口】调用setBeanFactory方法

15:49:12.528 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改

15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【InitializingBean接口】调用afterPropertiesSet方法

15:49:12.528 [main] INFO com.tom.lifecycle.Author - 【init-method】调用的init-method属性指定的初始化方法

15:49:12.528 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改

15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 初始化Spring容器成功 ========

15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - Author(name=Tom, address=湖南长沙, age=18, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@26653222: defining beans [beanPostProcessor,author]; root of factory hierarchy, beanName=author)

15:49:12.531 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 开始销毁Spring容器 ========

15:49:12.532 [Thread-0] INFO com.tom.lifecycle.Author - 【DiposibleBean接口】调用destroy方法

15:49:12.533 [Thread-0] INFO com.tom.lifecycle.Author - 【destroy-method】调用的destroy-method属性指定的初始化方法

我们看到,整个执行和我们一开始绘制的流程图一致。但是为什么我们要实现BeanFactoryPostProcessor接口呢?我们进入到BeanFactoryPostProcessor的源码如下:

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;

public interface BeanFactoryPostProcessor {

void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;

}

BeanFactoryPostProcessor接口只有一个postProcessBeanFactory()方法,BeanFactoryPostProcessor:在BeanFactory标准初始化之后可以进行修改。将加载所有Bean定义,但是还没有实例化Bean。这个方法允许重新覆盖或者添加属性甚至快速的初始化bean。初次看到可能不知道postProcessBeanFactory()到底是干嘛的。要想透彻理解这个方法的作用,下面来进入到BeanFactoryPostProcessor的源码,理解一下postProcessBeanFactory()的参数,我们可以利用这些参数做一些操作。

通过参数来看,只有一个ConfigurableListableBeanFactory类,这个类的可以提供分析、修改Bean定义和预先实例化单例的功能。我们再进入到ConfigurableListableBeanFactory的源码中:

public interface ConfigurableListableBeanFactory extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

//忽略被给定注入依赖类型 ,例如String

void ignoreDependencyType(Class<?> var1);

//略被给定注入依赖接口 。这个通常被使用由ApplicationContext去注册依赖,可以以多种方式实现。例如BeanFactory通过BeanFactoryAware,ApplicationContext 通过ApplicationContextAware。默认情况下,仅BeanFactoryAware接口是被忽略,需要忽略其他接口,调用此方法

void ignoreDependencyInterface(Class<?> var1);

//注册一个特定类型依赖伴随着相应的Autowired值。这个是准备被用于应该可以Autowire而不是在这个工厂被定义的Bean的工厂/上下文引用。例如 将ApplicationContext类型的依赖项解析为Bean所在的ApplicationContext实例。注意~在普通的BeanFactory中没有注册这样的默认类型,甚至连BeanFactory接口本身都没有

void registerResolvableDependency(Class<?> var1, Object var2);

//确认这个被指定的Bean是否是一个Autowire候选,将被注入到其他声明匹配类型的依赖的Bean中

boolean isAutowireCandidate(String var1, DependencyDescriptor var2) throws NoSuchBeanDefinitionException;

//根据指定的beanName返回被注册的Bean定义,允许访问其属性值和构造函数参数值(可以在BeanFactory后期处理期间被修改)。这个被返回的BeanDefinition对象不应该是副本而是原始在工厂被注册的。这意味着如果需要它可以被转换为更具体的实现类型。注意这个方法只能获得本地工厂BeanDefinition

BeanDefinition getBeanDefinition(String var1) throws NoSuchBeanDefinitionException;

//冻结全部Bean定义,给被注册的Bean定义发信号告诉它们今后不再被修改和进一步后续处理。它允许Factory去积极缓存Bean定义元数据

void freezeConfiguration();

//返回该工厂的BeanDefinnition是否被冻结

boolean isConfigurationFrozen();

//确保所有非懒加载的单例Bean被实例化,包括FactoryBean

void preInstantiateSingletons() throws BeansException;

}

通过以上演示和分析,我们应该大概能够了解ConfigurableListableBeanFactory的作用,基本就都是对于Bean定义的操作。至此我们还没有看到BeanPostProcessor 和InstantiationAwareBeanPostProcessor的调用。下面我们把BeanPostProcessor 和InstantiationAwareBeanPostProcessor的实现补充上来,再看完整的执行流程

2.3 实现BeanPostProcessor

=======================

创建GPBeanPostProcessor类,并实现BeanPostProcessor 接口,具体代码如下:

package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeansException;

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

@Slf4j

public class GPBeanPostProcessor implements BeanPostProcessor {

public GPBeanPostProcessor(){

log.info(“调用BeanPostProcessor实现类构造器!!”);

}

public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {

log.info(“BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改”);

return o;

}

public Object postProcessAfterInitialization(Object o, String s) throws BeansException {

log.info(“BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改”);

return o;

}

}

ApplicationContext 可以在BeanDefinition中自动检测到实现了BeanPostProcessor的Bean,并且把这些Bean应用于随后的Bean创建。普通的BeanFactory允许对后处理器进行程序化注册,通过工厂应用于所有Bean创建。BeanPostProcessor接口中主要有两个方法:

方法名

解释

postProcessBeforeInitialization

在Bean实例化回调(例如InitializingBean的afterPropertiesSet 或者一个定制的init-method)之前应用此BeanPostProcessor

postProcessAfterInitialization

在bean实例化回调(例如InitializingBean的afterPropertiesSet 或者一个定制的init-method)之后应用此BeanPostProcessor

2.4 实现InstantiationAwareBeanPostProcessor

=========================================

创建GPInstantiationAwareBeanPostProcessor类,并实现InstantiationAwareBeanPostProcessorAdapter接口,具体代码如下:

package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeansException;

import org.springframework.beans.PropertyValues;

import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

import java.beans.PropertyDescriptor;

@Slf4j

public class GPInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

public GPInstantiationAwareBeanPostProcessor() {

super();

log.info(“调用InstantiationAwareBeanPostProcessorAdapter实现类构造器!!”);

}

// 接口方法、实例化Bean之前调用

@Override

public Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {

log.info(“InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法”);

return null;

}

// 接口方法、实例化Bean之后调用

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

log.info(“InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法”);

return bean;

}

// 接口方法、设置某个属性时调用

@Override

public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

log.info(“InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法”);

return pvs;

}

}

实现InstantiationAwareBeanPostProcessorAdapter的Bean之后,可以在实例化成功之后,做一些校验或者补充些内容或者把Bean包装代理注入。实现InstantiationAwareBeanPostProcessorAdapter的Bean之后,不会影响容器正常处理每一个实例化的Bean,其子类仅仅只是根据需要覆盖父类的方法。

注意,只有在实际需要 InstantiationAwareBeanPostProcessor 功能时才推荐此基类。如果我们所需要的只是简单的BeanPostProcessor功能,那么直接实现更简单的接口即可。

下面详细介绍一下InstantiationAwareBeanPostProcessorAdapter接口中的所有方法:

方法名

解释

postProcessBeforeInstantiation

在实例化目标Bean之前应用此BeanPostProcessor。这个返回的Bean也许是一个代理代替目标Bean,有效地抑制目标Bean的默认实例化。如果此方法返回一个非空对象,则Bean的创建过程将被短路。唯一的进一步处理被应用是BeanPostProcessor.postProcessAfterInitialization(java.lang.Object, java.lang.String)方法(改变了Bean的生命周期实例化之后直接进入BeanPostProcessor.postProcessAfterInitialization)回调来自于配置好的BeanPostProcessors。这个回调将仅被应用于有Bean Class的BeanDefintions。特别是,它不会应用于采用”factory-method“的Bean。后处理器可以实现扩展的SmartInstantiationAwareBeanPostProcessor接口,以便预测它们将返回的Bean对象的类型

postProcessPropertyValues

在工厂将给定的属性值应用到给定的Bean之前,对给定的属性值进行后处理。允许检查全部依赖是否已经全部满足,例如基于一个@Required在Bean属性的Setter方法上。还允许替换要应用的属性值,通常通过基于原始的PropertyValues创建一个新的MutablePropertyValues实例,添加或删除特定的值

postProcessAfterInitialization

在Bean初始化回调(如InitializingBean的afterPropertiesSet或者定制的init-method)之后,应用这个BeanPostProcessor去给一个新的Bean实例。Bean已经配置了属性值,返回的Bean实例可能已经被包装。
如果是FactoryBean,这个回调将为FactoryBean实例和其他被FactoryBean创建的对象所调用。这个post-processor可以通过相应的FactoryBean实例去检查决定是否应用FactoryBean或者被创建的对象或者两个都有。这个回调在一个由InstantiationAwareBeanPostProcessor短路的触发之后将被调用

2.5 修改配置文件

==========

完整的配置文件内容如下:

<?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:p=“http://www.springframework.org/schema/p”

xmlns:aop=“http://www.springframework.org/schema/aop” xmlns:tx=“http://www.springframework.org/schema/tx”

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

<bean id=“author” class=“com.tom.lifecycle.Author”

init-method=“beanInit”

destroy-method=“beanDestory”

scope=“singleton”

p:name=“Tom” p:address=“湖南长沙” p:age=“18”/>

2.6 运行结果

========

最后,我们再次运行BeanLifeCycleTest测试类,看到如下运行结果:

15:56:20.030 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - 调用BeanFactoryPostProcessor实现类构造器!!

15:56:20.045 [main] INFO com.tom.lifecycle.GPBeanFactoryPostProcessor - BeanFactoryPostProcessor调用postProcessBeanFactory方法

15:56:20.046 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - 调用BeanPostProcessor实现类构造器!!

15:56:20.047 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - 调用InstantiationAwareBeanPostProcessorAdapter实现类构造器!!

15:56:20.051 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法

15:56:20.052 [main] INFO com.tom.lifecycle.Author - 【构造器】调用Tom类的构造器实例化

15:56:20.069 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法

15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【注入属性】address

15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【注入属性】age

15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【注入属性】name

15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【BeanNameAware接口】调用setBeanName方法

15:56:20.092 [main] INFO com.tom.lifecycle.Author - 【BeanFactoryAware接口】调用setBeanFactory方法

15:56:20.093 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改

15:56:20.093 [main] INFO com.tom.lifecycle.Author - 【InitializingBean接口】调用afterPropertiesSet方法

15:56:20.093 [main] INFO com.tom.lifecycle.Author - 【init-method】调用的init-method属性指定的初始化方法

15:56:20.093 [main] INFO com.tom.lifecycle.GPBeanPostProcessor - BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改

15:56:20.093 [main] INFO com.tom.lifecycle.GPInstantiationAwareBeanPostProcessor - InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法

15:56:20.097 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 初始化Spring容器成功 ========

15:56:20.098 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - Author(name=Tom, address=湖南长沙, age=16, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@26653222: defining beans [beanPostProcessor,beanFactoryPostProcessor,instantiationAwareBeanPostProcessor,author]; root of factory hierarchy, beanName=author)

15:56:20.098 [main] INFO com.tom.lifecycle.BeanLifeCycleTest - ====== 开始销毁Spring容器 ========

15:56:20.099 [Thread-0] INFO com.tom.lifecycle.Author - 【DiposibleBean接口】调用destroy方法

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!**

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-9fIjFG8h-1712979828078)]

惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

[外链图片转存中…(img-hIlH6bRA-1712979828079)]

[外链图片转存中…(img-MjOmJ9EH-1712979828079)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-UKDMR5o8-1712979828079)]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/740603
推荐阅读
相关标签
  

闽ICP备14008679号