Spring创建Bean的生命周期详析

yizhihongxing

首先,Spring中Bean创建的生命周期分为以下几个步骤:

  1. Bean实例化
  2. 属性设置(依赖注入)
  3. Aware回调(例如BeanNameAware、BeanFactoryAware)
  4. BeanPostProcessor前置处理
  5. 初始化方法调用
  6. BeanPostProcessor后置处理

下面我们来一步步分析每一个步骤。

Bean实例化

在Spring容器中,Bean实例化通常有两个过程:实例化和初始化。实例化是创建Bean实例的过程,通常是通过构造函数或工厂方法进行的。初始化是为Bean设置属性,通常是通过依赖注入完成的。

对于实例化过程,我们来看一个示例,假设有一个类叫做MyBean

public class MyBean {
    public MyBean() {
        System.out.println("MyBean: 实例化");
    }
}

在Spring容器中,使用如下方式配置 MyBean:

<bean id="myBean" class="com.example.MyBean"/>

当我们启动应用程序时,会看到输出 MyBean: 实例化,这表示MyBean已经成功实例化。

属性设置(依赖注入)

在实例化Bean后,Spring会为Bean注入属性,也就是依赖注入。依赖注入有多种方式,例如:

  • 构造函数注入
  • Setter方法注入
  • 属性注入

下面我们以Setter方法注入为例,假设有另外一个类叫做MyBeanDep,它需要注入到MyBean中作为一个依赖:

public class MyBeanDep {
    public void init() {
        System.out.println("MyBeanDep: 初始化");
    }
}

我们将MyBeanDep注入到MyBean中:

<bean id="myBeanDep" class="com.example.MyBeanDep"/>

<bean id="myBean" class="com.example.MyBean">
    <property name="myBeanDep" ref="myBeanDep"/>
</bean>

这里我们使用<property>标签来设置属性,其中name属性指定了要设置的属性名,ref属性指定了要注入的依赖Bean的ID。

Aware回调

Aware接口是Spring提供的一组接口,实现这些接口的Bean可以获取Spring容器的一些资源,例如Bean的名称、BeanFactory等。 例如,我们可以实现BeanNameAware接口,获取自己在Spring容器中的名称:

public class MyBean implements BeanNameAware {
    private String name;

    public void setBeanName(String name) {
        this.name = name;
    }
}

在Spring容器中,我们这样配置MyBean:

<bean id="myBean" class="com.example.MyBean"/>

启动应用程序时,Spring会调用setBeanName方法,并将MyBean在容器中的名称传入。

BeanPostProcessor前置处理

BeanPostProcessor是Spring提供的一个接口,可以用来在Bean实例化、初始化过程中对Bean进行处理。Spring内置了许多实现了BeanPostProcessor接口的类,例如ApplicationContextAwareProcessor、AutowiredAnnotationBeanPostProcessor等。

例如,我们可以实现一个简单的BeanPostProcessor,打印出Bean的实例化和初始化方法被调用的时间:

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        System.out.println(name + ": 处理前置处理,当前时间:" + new Date());
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        System.out.println(name + ": 处理后置处理,当前时间:" + new Date());
        return bean;
    }
}

在Spring容器中,我们这样配置Bean:

<bean id="myBeanPostProcessor" class="com.example.MyBeanPostProcessor"/>

<bean id="myBean" class="com.example.MyBean">
    <property name="myBeanDep" ref="myBeanDep"/>
</bean>

启动应用程序,我们可以看到输出类似于以下内容:

myBeanPostProcessor: 处理前置处理,当前时间: Thu Aug 19 23:40:03 CST 2021
myBean: 实例化
myBean: 处理前置处理,当前时间: Thu Aug 19 23:40:04 CST 2021
myBean: 处理后置处理,当前时间: Thu Aug 19 23:40:04 CST 2021
MyBeanDep: 初始化
myBean: 处理后置处理,当前时间: Thu Aug 19 23:40:04 CST 2021

初始化方法调用

初始化方法是Spring容器为Bean设置完属性、完成Aware回调、执行完BeanPostProcessor前置处理后调用的方法。 在Spring中,Bean可以通过实现InitializingBean接口或在配置文件中使用init-method属性来指定初始化方法。

例如,我们在MyBean类中定义初始化方法:

public class MyBean implements InitializingBean {
    public void afterPropertiesSet() throws Exception {
        System.out.println("MyBean: 初始化");
    }
}

在Spring容器中,我们这样配置Bean:

<bean id="myBean" class="com.example.MyBean">
    <property name="myBeanDep" ref="myBeanDep"/>
    <init-method>afterPropertiesSet</init-method>
</bean>

启动应用程序,我们可以看到输出类似于以下内容:

myBeanPostProcessor: 处理前置处理,当前时间: Thu Aug 19 23:50:29 CST 2021
myBean: 实例化
myBean: 处理前置处理,当前时间: Thu Aug 19 23:50:30 CST 2021
myBean: 处理后置处理,当前时间: Thu Aug 19 23:50:30 CST 2021
MyBeanDep: 初始化
MyBean: 初始化
myBean: 处理后置处理,当前时间: Thu Aug 19 23:50:30 CST 2021

BeanPostProcessor后置处理

BeanPostProcessor后置处理是在Bean初始化方法调用后执行的。有时候我们需要在Bean初始化后做一些其他的操作,例如缓存Bean或者检查Bean状态是否正确。

例如,我们实现一个BeanPostProcessor,输出Bean是否已正确初始化:

public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof MyBean) {
            MyBean myBean = (MyBean) bean;
            if (myBean.getMyBeanDep() != null) {
                System.out.println("MyBean已正确初始化!");
            } else {
                System.out.println("MyBean未正确初始化!");
            }
        }
        return bean;
    }
}

启动应用程序,我们可以看到输出类似于以下内容:

myBeanPostProcessor: 处理前置处理,当前时间: Thu Aug 19 23:56:47 CST 2021
myBean: 实例化
myBean: 处理前置处理,当前时间: Thu Aug 19 23:56:48 CST 2021
myBean: 处理后置处理,当前时间: Thu Aug 19 23:56:48 CST 2021
MyBeanDep: 初始化
MyBean已正确初始化!
myBean: 处理后置处理,当前时间: Thu Aug 19 23:56:48 CST 2021

通过上述示例,我们可以清晰了解Spring中Bean创建的完整生命周期及其每一个步骤。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring创建Bean的生命周期详析 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • java内存管理关系及内存泄露的原理分析

    Java内存管理关系及内存泄露的原理分析 Java内存管理是Java程序设计中非常重要的一部分,它涉及到内存的分配、使用和释放。正确地管理内存可以提高程序的性能和稳定性,而内存泄露则可能导致程序的崩溃和性能下降。本文将详细讲解Java内存管理的关系以及内存泄露的原理,并提供两个示例来说明。 Java内存管理关系 Java内存管理主要涉及到以下几个方面: 堆(…

    other 2023年8月2日
    00
  • java如何用递归方法求阶乘

    可以使用递归方法来求阶乘,递归可以将问题划分为多个小问题,然后用相同的方法解决它们,最后将它们的答案组合在一起。下面是Java代码示例: public class Factorial { public static void main(String[] args) { int num = 5; int result = factorial(num); Sys…

    other 2023年6月27日
    00
  • 服务名无效。请键入nethelpmsg2185以获得更多的帮助。

    以下是详细讲解“服务名无效。请键入nethelpmsg2185以获得更多的帮助。”的完整攻略: 服务名无效。请键入nelpmsg2185以获得更多的帮助。 当在Windows系统中启动或停止服务时,可能会遇到“服务名无效。请入nethelpmsg2185以获得更多的帮助。”的错误提示。本攻略将介绍如何解决这个问题。 步骤一:检查服务名是否正确 首先需要检查服…

    other 2023年5月10日
    00
  • 支付宝APP支付(IOS手机端+java后台)版

    下面是支付宝APP支付(IOS手机端+java后台)版的完整攻略。 准备工作 在开始之前,需要完成以下准备工作: 开通支付宝商家账号,获取应用ID和私钥。 集成SDK,包括iOS和Java SDK。 配置AliSDK的参数,包括应用ID、私钥等等。 在支付宝商家后台配置应用信息,包括回调URL、权限等等。 客户端代码 SDK下载 首先,需要将支付宝提供的SD…

    other 2023年6月26日
    00
  • 实况足球2016黑屏怎么办 N卡频繁黑屏的快速解决方法

    实况足球2016黑屏怎么办 如果在玩实况足球2016时,出现了黑屏的情况,可能会让玩家感到非常困扰。下面介绍一些常见解决方法。 方法一:更改游戏设置 打开实况足球2016游戏,点击“选项”按钮。 在弹出的选项设置窗口中,依次点击“显示”、“窗口模式”、“1920 X 1080”等选项,设置屏幕分辨率。 点击确定保存更改,重启实况足球2016游戏。 方法二:更…

    other 2023年6月27日
    00
  • Winform自定义控件在界面拖动、滚动鼠标时闪烁的解决方法

    Winform自定义控件在界面拖动、滚动鼠标时闪烁的问题,通常是由于控件的重绘操作频繁引起的。因此,需要采取一些措施来减少控件的重绘频率,以提高界面的流畅度和稳定性。 方法一:使用双缓冲技术 双缓冲技术是一种常用的减少控件闪烁的方法,可以将控件的重绘操作先绘制在内存中,再将内存中的内容一次性绘制到控件上,从而避免频繁引起界面重绘而导致的闪烁问题。 在使用双缓…

    other 2023年6月27日
    00
  • Android开发仿QQ空间根据位置弹出PopupWindow显示更多操作效果

    Android开发仿QQ空间根据位置弹出PopupWindow显示更多操作效果攻略 简介 在Android开发中,我们可以使用PopupWindow来实现类似QQ空间的效果,即根据位置弹出一个窗口,显示更多操作选项。本攻略将详细介绍如何实现这一效果。 步骤 步骤一:准备工作 在开始之前,确保你已经具备以下条件:- 了解Android开发基础知识- 已经创建一…

    other 2023年8月26日
    00
  • json数据进行sql查询

    json数据进行SQL查询 在现代的应用程序中,JSON(JavaScript Object Notation)已经成为最常用的数据交换格式之一。随着日益增长的JSON数据存储,在许多情况下,我们需要使用SQL查询来检索JSON对象中特定属性的值。在本文中,我们将提供一些关于如何在SQL中使用JSON数据的指导。 使用JSON函数 SQL 2016 引入了几…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部