一文带你深入理解SpringBean生命周期之Aware详解

简介: 一文带你深入理解SpringBean生命周期之Aware详解

概述


相比大家在看Spring的源码看到很多实现了Aware接口的类,比如实现了BeanNameAware, BeanFactoryAware等。那这一些列的Aware接口用什么作用呢?他们又是在什么时候调用的呢?一切答案将在本篇文章中为大家揭晓。


Aware接口介绍


/**
 * A marker superinterface indicating that a bean is eligible to be notified by the
 * Spring container of a particular framework object through a callback-style method.
 * The actual method signature is determined by individual subinterfaces but should
 * typically consist of just one void-returning method that accepts a single argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default functionality.
 * Rather, processing must be done explicitly, for example in a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * for an example of processing specific {@code *Aware} interface callbacks.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 */
public interface Aware {
}

上面是Aware接口的源码定义,我们先来看下他的注释,Spring的注释还是写的非常不错的,我们翻译下:

Aware 接口是一个具有标识作用的超级接口,指示 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。Aware 接口是一个空接口,具体的实现由各个子接口决定,且该接口通常只包含一个单个参数并且返回值为void的方法。可以理解就是 set 方法。该方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。注意,仅实现Aware接口,不会提供任何默认功能,需要明确的指定实现哪个子接口

通俗的来说,Aware翻译过来的意思是有感知的,察觉的,如果类上实现了该接口,表明对什么有感知,比如BeanNameAware, 表示知道了自己的Bean Name。


作用


为什么要有个Aware接口?

因为我们在实际的开发过程中,有些Bean可能需要用到Spring容器本身的功能资源,所以Spring容器中的Bean此时就要意识到Spring容器的存在才能调用Spring所提供的资源。我们通过Spring提供的一系列接口Spring Aware来实现具体的功能。


内置的Aware


我们可以看到Spring内置了很多的Aware。image.png

名称 用途 所属容器 回调点
BeanNameAware 获取bean名称 BeanFactory Bean后处理器的BeforeInitialization方法之前
BeanClassLoaderAware 获取bean的类加载器 BeanFactory Bean后处理器的BeforeInitialization方法之前
BeanFactoryAware 获取bean工厂(建议用下面的ApplicationContextAware) BeanFactory Bean后处理器的BeforeInitialization方法之前
EnvironmentAware 获取环境相关信息,如属性、配置信息等 ApplicationContext Bean后处理器的BeforeInitialization方法中
EmbeddedValueResolverAware 获取值解析器 ApplicationContext Bean后处理器的BeforeInitialization方法中
ResourceLoaderAware 获取资源加载器 ApplicationContext Bean后处理器的BeforeInitialization方法中
ApplicationEventPublisherAware 获取事件广播器,发布事件使用 ApplicationContext Bean后处理器的BeforeInitialization方法中
MessageSourceAware 获取消息资源 ApplicationContext Bean后处理器的BeforeInitialization方法中
ApplicationContextAware 获取ApplicationContext ApplicationContext Bean后处理器的BeforeInitialization方法中


实践案例


  1. 定义bean实现对应的aware接口
@Data
@Slf4j
@ToString
@Accessors(chain = true)
public class BeanLifeCycle implements InitializingBean, BeanNameAware, BeanFactoryAware, EnvironmentAware, ApplicationContextAware {
    @Value("${prop:hello}")
    private String prop ;
    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;
    private Environment environment;
    public BeanLifeCycle() {
        log.info("#################BeanLifeCycle 实例化");
    }
    public void init() {
        log.info("#################BeanLifeCycle 调用init-mthod 初始化");
    }
    public void destroy() {
        log.info("#################BeanLifeCycle 销毁");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("#################BeanLifeCycle 调用afterPropertiesSet方法, 查看属性值prop:[{}],已经被赋值", prop);
        log.info("#################BeanLifeCycle 调用afterPropertiesSet 初始化");
    }
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("@@@@@@@@@@@@@@@@@@ beanFactory: [{}]", beanFactory);
    }
    @Override
    public void setBeanName(String beanName) {
        log.info("@@@@@@@@@@@@@@@@@@ beanName: [{}]", beanName);
        this.beanName = beanName;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("@@@@@@@@@@@@@@@@@@ applicationContext: [{}]", applicationContext);
        this.applicationContext = applicationContext;
    }
    @Override
    public void setEnvironment(Environment environment) {
        log.info("@@@@@@@@@@@@@@@@@@ environment: [{}]", environment);
        this.environment = environment;
    }
}
  1. 执行结果

image.png

image.png

执行结果中输出了awre接口执行的内容。


源码解析


现在我们从源码角度分析下aware接口的执行时机。

image.png

通过debug追踪到执行是在创建bean的初始化阶段。

  1. AbstractAutowireCapableBeanFactorydoCreateBean()是创建bean的入口。
  2. AbstractAutowireCapableBeanFactoryinitializeBean()方法是bean的初始化入口。

我们重点关注Bean的初始化。

image.png

可以看到有两个点回执行Aware接口,我们先看下第一个方法invokeAwareMethods()

image.png

很明显,上面标记的1,2,3分别执行BeanNameAwareBeanClassLoaderAwareBeanFactoryAware 3个接口的方法。

ApplicationContextAwareProcessor实现了BeanPostProcessor, 是Spring内置的的一个处理器,在Bean初始化化前后执行,它也是执行Aware接口的另外一个入口。

image.png

image.png

ok, 到这里我们明白了这个Aware接口的执行时机。

ApplicationContextAwareProcessor这个处理器本身是什么时候注入到容器中的呢?

是在创建容器的时候AbstractApplicationContext#refresh()方法中调用了prepareBeanFactory方法。

image.png


总结


Bean创建时,会调用Aware接口,设置容器对应的资源属性,扩展Bean的能力。

1671110021709.jpg

BeanFactory初始化容器方式

在加载bean的步骤中,创建bean之后,调用bean后处理器之前,回调表格中的3个Aware接口。

ApplicationContext初始化容器方式

  1. 调用BeanFactory方式的3个Aware接口;
  2. 在加载bean之前创建一个ApplicationContextAwareProcessor,注册在AbstractBeanFactorybeanPostProcessors属性中。然后在加载bean的步骤中,调用bean后处理器的postProcessBeforeInitialization方法过程中,回调表格中的6个Aware接口。
目录
相关文章
|
7月前
|
XML Java 数据格式
SpringBean的生命周期
SpringBean的生命周期
72 0
|
24天前
|
Java 容器 Spring
Bean的实例化阶段
经过第一阶段,所有bean定义都通过BeanDefinition的方式注册到BeanDefinitionRegistry中当某个请求通过容器的getBean方法请求某个对象,或者因为依赖关系容器需要隐式的调用getBean时,就会触发第二阶段的活动:容器会首先检查所请求的对象之前是否已经实例化完成。 如果没有,则会根据注册的BeanDefinition所提供的信息实例化被请求对象,并为其注入依赖。 当该对象装配完毕后,容器会立即将其返回给请求方法使用。BeanFactory只是Spring IoC容器的一种实现,如果没有特殊指定,它采用采用延迟初始化策略:只有当访问容器中的某个对象时,才对
|
3月前
|
Java 开发者 Spring
Bean生命周期介绍
Spring Boot 的 Bean 生命周期管理是其核心功能之一,负责应用程序中 Java 对象(称为 Beans)的创建、配置、初始化和销毁。此功能提供了灵活的依赖注入方式,便于组件化开发。Bean 生命周期包括实例化、属性注入、初始化方法调用、使用及销毁方法调用等阶段。应用场景涵盖依赖注入、配置管理、组件扩展及切面编程。通过实现特定接口或注解,开发者可轻松管理对象生命周期,优化应用性能。示例代码展示了如何通过日志观察 Bean 生命周期的不同阶段。
114 3
|
6月前
|
Java 开发者 Spring
Spring的Bean的生命周期各个阶段扩展方法
Spring的Bean的生命周期各个阶段扩展方法
|
7月前
|
XML Java 数据格式
Spring框架学习 -- Bean的生命周期和作用域
Spring框架学习 -- Bean的生命周期和作用域
56 2
|
Java 容器 Spring
Bean生命周期
Bean生命周期
|
7月前
|
Java 开发者 Spring
Bean 的生命周期了解么
Bean 的生命周期了解么
|
前端开发 Java Spring
一文带你深入理解SpringBean生命周期之InitializingBean详解
一文带你深入理解SpringBean生命周期之InitializingBean详解
617 0
一文带你深入理解SpringBean生命周期之InitializingBean详解
|
Java Spring 容器
bean的生命周期
bean的生命周期
56 0