大厂高频面试题Spring Bean生命周期最详解(1)

this.address = address;

}

public void setAge(int age) {

log.info(“【注入属性】age”);

this.age = age;

}

// 实现BeanFactoryAware接口的方法

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

log.info(“【BeanFactoryAware接口】调用setBeanFactory方法”);

this.beanFactory = beanFactory;

}

// 实现BeanNameAware接口的方法

public void setBeanName(String beanName) {

log.info(“【BeanNameAware接口】调用setBeanName方法”);

this.beanName = beanName;

}

// 实现DiposibleBean接口的方法

public void destroy() throws Exception {

log.info(“【DiposibleBean接口】调用destroy方法”);

}

// 实现InitializingBean接口的方法

public void afterPropertiesSet() throws Exception {

log.info(“【InitializingBean接口】调用afterPropertiesSet方法”);

}

// 通过的init-method属性指定的初始化方法

public void beanInit() {

log.info(“【init-method】调用的init-method属性指定的初始化方法”);

}

// 通过的destroy-method属性指定的初始化方法

public void beanDestory() {

log.info(“【destroy-method】调用的destroy-method属性指定的初始化方法”);

}

}

在配置Spring配置文件中加入如下内容:

<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.2 演示BeanFactoryPostProcessor的执行

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

1.创建GPBeanFactoryPostProcessor类,并实现BeanFactoryPostProcessor接口,具体代码如下:

package com.tom.lifecycle;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeansException;

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

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

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

@Slf4j

public class GPBeanFactoryPostProcessor implements BeanFactoryPostProcessor{

public GPBeanFactoryPostProcessor() {

super();

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

}

public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

log.info(“BeanFactoryPostProcessor调用postProcessBeanFactory方法”);

BeanDefinition bd = configurableListableBeanFactory.getBeanDefinition(“author”);

bd.getPropertyValues().addPropertyValue(“age”, “16”);

}

}

2.在配置Spring配置文件中加入如下内容:

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实现类构造器!!”);

最后

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

image

image

其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣,

f4j

public class GPInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {

public GPInstantiationAwareBeanPostProcessor() {

super();

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

最后

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

[外链图片转存中…(img-gB4o9mhZ-1714672681227)]

[外链图片转存中…(img-AIRtAeyn-1714672681228)]

其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣,

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值