杨维勇 發表於 2026-1-13 14:45:51

深度解析Spring Bean生命周期以及LomBok插件

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、传统Java vs Spring:Bean生命周期核心差异</li><li>二、Spring Bean生命周期完整阶段拆解</li><li>三、Bean生命周期回调方法:3种实现方式与优先级</li><ul class="second_class_ul"><li>方式一:接口实现(InitializingBean + DisposableBean)</li><ul class="third_class_ul"><li>1. 代码实现</li><li>2. 注意事项</li></ul><li>方式二:XML配置(init-method + destroy-method)</li><ul class="third_class_ul"><li>1. 代码实现</li><li>2. 核心优势</li></ul><li>方式三:注解实现(@PostConstruct + @PreDestroy)</li><ul class="third_class_ul"><li>1. 代码实现</li><li>2. 核心优势</li></ul></ul><li>四、关键扩展:Bean后置处理器(BeanPostProcessor)</li><ul class="second_class_ul"><li>1. 核心作用</li><ul class="third_class_ul"></ul><li>2. 实现步骤</li><ul class="third_class_ul"><li>步骤1:创建后置处理器类</li><li>步骤2:将后置处理器注入IOC容器</li><li>3. 执行效果说明</li></ul></ul><li>五、实战测试:验证Bean生命周期流程</li><ul class="second_class_ul"><li>1. 测试类编写</li><ul class="third_class_ul"></ul><li>2. 测试结果与分析</li><ul class="third_class_ul"></ul></ul><li>六、核心知识点总结(面试必背)</li><ul class="second_class_ul"></ul><li>七、LomBok</li><ul class="second_class_ul"></ul></ul></div><p>在Spring框架中,Bean的生命周期是核心知识点之一,也是面试中的高频考点。相比于传统Java应用中Bean简单的&ldquo;实例化-使用-垃圾回收&rdquo;流程,Spring IOC容器对Bean的生命周期提供了完整的管理能力,支持在特定阶段执行定制化任务。本文将从核心差异入手,层层拆解Spring Bean的生命周期阶段,结合具体代码案例详解生命周期回调方法的实现方式,并补充Bean后置处理器的关键知识点,帮助大家彻底掌握这一核心内容。</p>
<p class="maodian"></p><h2>一、传统Java vs Spring:Bean生命周期核心差异</h2>
<p>在传统Java应用中,Bean的生命周期逻辑非常简单,完全由JVM主导:</p>
<ul><li>实例化:通过<code>new</code>关键字调用构造器创建Bean实例;</li><li>使用:实例创建完成后直接调用方法即可使用;</li><li>销毁:当Bean长期不被使用,失去引用后,JVM自动执行垃圾回收。</li></ul>
<p>而Spring中的Bean生命周期则由IOC容器全程管理,流程更复杂,但灵活性更高&mdash;&mdash;Spring允许我们在Bean生命周期的关键节点插入自定义逻辑,实现对Bean的精细化管控。这种管控能力也是Spring框架核心优势之一。</p>
<p class="maodian"></p><h2>二、Spring Bean生命周期完整阶段拆解</h2>
<p>Spring Bean的生命周期从IOC容器初始化开始,到IOC容器关闭结束,整个流程可拆解为8个核心阶段,各阶段按顺序依次执行:</p>
<ul><li><strong>Bean对象创建</strong>:IOC容器初始化时,通过Java反射机制调用Bean的无参构造器,生成Bean的实例对象;</li><li><strong>Bean对象属性注入</strong>:同样通过反射机制,调用Bean的setter方法,将配置文件或注解中定义的属性值注入到Bean实例中;</li><li><strong>Bean初始化前操作</strong>:由Bean后置处理器(BeanPostProcessor)的<code>postProcessBeforeInitialization</code>方法负责执行,属于全局定制化操作;</li><li><strong>Bean对象初始化</strong>:需在Bean配置时指定初始化方法(如接口实现、XML配置、注解方式),容器会调用该方法执行初始化逻辑;</li><li><strong>Bean初始化后操作</strong>:由Bean后置处理器的<code>postProcessAfterInitialization</code>方法负责执行,同样是全局生效的定制化操作;</li><li><strong>Bean对象就绪可用</strong>:经过以上阶段后,Bean实例已完全初始化完成,可通过IOC容器的<code>getBean()</code>方法获取并使用;</li><li><strong>Bean对象销毁</strong>:需在Bean配置时指定销毁方法,当IOC容器关闭时,容器会调用该方法执行销毁逻辑(如资源释放);</li><li><strong>IOC容器关闭</strong>:容器完成所有Bean的销毁后,自身关闭,生命周期结束。</li></ul>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026011314405678.png" /></p>
<blockquote><p>提示:核心记忆点&mdash;&mdash;&ldquo;创建-注入-初始化前后-就绪-销毁-容器关闭&rdquo;,其中初始化前后的操作由后置处理器主导,初始化和销毁需自定义方法并配置。</p></blockquote>
<p class="maodian"></p><h2>三、Bean生命周期回调方法:3种实现方式与优先级</h2>
<p>Spring允许我们通过&ldquo;生命周期回调方法&rdquo;在Bean的初始化(第4阶段)和销毁(第7阶段)时刻执行自定义逻辑(如资源加载、连接关闭等)。共有3种实现方式,且存在明确的优先级顺序。</p>
<p><strong>核心优先级规则</strong>:注解 &gt; 接口实现 &gt; XML配置</p>
<p class="maodian"></p><h3>方式一:接口实现(InitializingBean + DisposableBean)</h3>
<p>通过让Bean类实现Spring提供的<code>InitializingBean</code>(初始化回调)和<code>DisposableBean</code>(销毁回调)接口,重写接口中的方法即可实现定制逻辑。</p>
<p class="maodian"></p><p class="maodian"></p><p class="maodian"></p><h4>1. 代码实现</h4>
<div class="jb51code"><pre class="brush:java;">import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Dog implements InitializingBean, DisposableBean {
    private String name;
    private String owner;
    private int age;
    // 1. 无参构造器:阶段1(Bean对象创建)执行
    public Dog() {
      System.out.println("Dog对象被创建...");
    }
    // Setter方法:阶段2(属性注入)执行
    public void setName(String name) {
      System.out.println("调用setName方法....");
      this.name = name;
    }
    public void setOwner(String owner) {
      System.out.println("调用setOwner方法....");
      this.owner = owner;
    }
    public void setAge(int age) {
      System.out.println("调用setAge方法....");
      this.age = age;
    }
    @Override
    public String toString() {
      return "Dog{" +
                "name='" + name + '\'' +
                ", owner='" + owner + '\'' +
                ", age=" + age +
                '}';
    }
    // 2. 初始化回调:实现InitializingBean接口,阶段4执行
    // 该方法在属性注入完成后调用
    @Override
    public void afterPropertiesSet() throws Exception {
      System.out.println("调用接口:InitializingBean,方法:afterPropertiesSet,无参数");
    }
    // 3. 销毁回调:实现DisposableBean接口,阶段7执行
    // 该方法在容器关闭时调用
    @Override
    public void destroy() throws Exception {
      System.out.println("调用接口:DisposableBean,方法:destroy,无参数");
    }
}</pre></div>
<p class="maodian"></p><h4>2. 注意事项</h4>
<p>这种方式的<strong>缺点是耦合性高</strong>&mdash;&mdash;Bean类直接依赖Spring框架的接口,导致代码与Spring框架紧耦合,不利于后续的扩展和迁移。因此,在实际开发中,除非有特殊需求,否则不建议优先使用。</p>
<p class="maodian"></p><h3>方式二:XML配置(init-method + destroy-method)</h3>
<p>通过Spring的XML配置文件,在<code>&lt;bean&gt;</code>标签中通过<code>init-method</code>属性指定初始化方法名,通过<code>destroy-method</code>属性指定销毁方法名,无需Bean类实现任何接口,降低了耦合性。</p>
<h4>1. 代码实现</h4>
<p>首先,在Dog类中定义自定义的初始化和销毁方法(方法名可任意,无参数):</p>
<div class="jb51code"><pre class="brush:java;">public class Dog {
    private String name;
    private String owner;
    private int age;
    public Dog() {
      System.out.println("Dog对象被创建...");
    }
    // Setter方法省略...
    // 自定义初始化方法:对应init-method
    public void initDog() {
      System.out.println("XML配置:执行自定义初始化方法 initDog");
    }
    // 自定义销毁方法:对应destroy-method
    public void destroyDog() {
      System.out.println("XML配置:执行自定义销毁方法 destroyDog");
    }
    // toString方法省略...
}</pre></div>
<p>然后,在XML配置文件(applicationContext.xml)中配置属性:</p>
<div class="jb51code"><pre class="brush:xml;">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd"&gt;
    &lt;!-- 配置Dog Bean,指定初始化和销毁方法 --&gt;
    &lt;bean id="dog"
          class="com.qcby.Dog"
          p:name="admin"
          p:owner="aaa"
          p:age="18"
          init-method="initDog"
          destroy-method="destroyDog"/&gt;
&lt;/beans&gt;</pre></div>
<p class="maodian"></p><p class="maodian"></p><h4>2. 核心优势</h4>
<p>完全解耦:Bean类是纯Java类,不依赖任何Spring接口或注解,通用性更强,便于维护和迁移。适合基于XML配置的传统Spring项目。</p>
<p class="maodian"></p><h3>方式三:注解实现(@PostConstruct + @PreDestroy)</h3>
<p>通过JDK提供的<code>@PostConstruct</code>(初始化回调)和<code>@PreDestroy</code>(销毁回调)注解,直接标注在Bean类的方法上,实现定制逻辑。这是目前开发中最常用的方式,简洁高效且耦合性低。</p>
<h4>1. 代码实现</h4>
<p>首先,需要引入lombok依赖(若未引入,也可直接使用注解,不影响功能):</p>
<div class="jb51code"><pre class="brush:plain;">&lt;dependency&gt;
    &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
    &lt;artifactId&gt;lombok&lt;/artifactId&gt;
    &lt;version&gt;1.18.12&lt;/version&gt;
    &lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;</pre></div>
<p>然后,在Dog类中使用注解标注方法:</p>
<div class="jb51code"><pre class="brush:java;">import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Dog {
    private String name;
    private String owner;
    private int age;
    public Dog() {
      System.out.println("Dog对象被创建...");
    }
    // Setter方法省略...
    // 初始化回调:@PostConstruct,阶段4执行
    @PostConstruct
    public void initByAnnotation() {
      System.out.println("注解方式:执行@PostConstruct标注的初始化方法");
    }
    // 销毁回调:@PreDestroy,阶段7执行
    @PreDestroy
    public void destroyByAnnotation() {
      System.out.println("注解方式:执行@PreDestroy标注的销毁方法");
    }
    // toString方法省略...
}</pre></div>
<p>最后,在XML或注解配置中扫描该Bean(确保IOC容器能识别):</p>
<div class="jb51code"><pre class="brush:xml;">&lt;!-- XML配置扫描包 --&gt;
&lt;context:component-scan base-package="com.xxx"/&gt;</pre></div>
<h4>2. 核心优势</h4>
<p>1. 简洁高效:无需实现接口,无需XML配置,直接通过注解标注即可;2. 耦合性低:注解是JDK原生提供(非Spring专属),Bean类通用性强;3. 优先级最高:当多种方式同时存在时,注解标注的方法会优先执行。</p>
<p class="maodian"></p><h2>四、关键扩展:Bean后置处理器(BeanPostProcessor)</h2>
<p>Bean后置处理器是Spring提供的一种全局扩展机制,它不针对某个特定的Bean,而是对IOC容器中所有的Bean生效,主要作用于Bean初始化的前后两个阶段(对应生命周期的第3和第5阶段)。</p>
<p class="maodian"></p><h3>1. 核心作用</h3>
<ul><li>初始化前(postProcessBeforeInitialization):对初始化前的Bean实例进行增强或修改;</li><li>初始化后(postProcessAfterInitialization):对初始化后的Bean实例进行增强或修改(如AOP的动态代理就是基于此实现)。</li></ul>
<p class="maodian"></p><h3>2. 实现步骤</h3>
<p class="maodian"></p><h4>步骤1:创建后置处理器类</h4>
<div class="jb51code"><pre class="brush:java;">import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
// 自定义Bean后置处理器,实现BeanPostProcessor接口
public class MyBeanProcessor implements BeanPostProcessor {
    // 初始化前执行
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("☆☆☆ 后置处理器-初始化前:" + beanName + " = " + bean);
      return bean; // 必须返回bean实例,否则容器中无法获取到该Bean
    }
    // 初始化后执行
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("★★★ 后置处理器-初始化后:" + beanName + " = " + bean);
      return bean;
    }
}</pre></div>
<p class="maodian"></p><h4>步骤2:将后置处理器注入IOC容器</h4>
<p>后置处理器必须被IOC容器管理,才能生效。通过XML配置注入:</p>
<div class="jb51code"><pre class="brush:java;">&lt;!-- 注入Bean后置处理器 --&gt;
&lt;bean id="myBeanProcessor" class="com.gs.process.MyBeanProcessor"/&gt;</pre></div>
<p class="maodian"></p><h4>3. 执行效果说明</h4>
<p>当IOC容器初始化时,会对所有Bean执行以下流程:</p>
<p>Bean创建 &rarr; 属性注入 &rarr; 后置处理器初始化前方法 &rarr; Bean初始化方法 &rarr; 后置处理器初始化后方法 &rarr; Bean就绪可用</p>
<p>控制台会输出类似如下内容:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026011314405661.png" /></p>
<p class="maodian"></p><h2>五、实战测试:验证Bean生命周期流程</h2>
<p>为了更直观地理解整个生命周期流程,我们通过一个完整的测试案例来验证。</p>
<p class="maodian"></p><h3>1. 测试类编写</h3>
<div class="jb51code"><pre class="brush:java;">import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.xxx.Dog;
public class LifeCycleTest {
    @Test
    public void testLifeCycle() {
      System.out.println("-------容器初始化阶段---------");
      // 初始化IOC容器(此时会触发Bean的创建、属性注入、初始化等流程)
      ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
      System.out.println("-------对象使用阶段---------");
      // 获取Bean实例并使用
      Dog dog = ac.getBean("dog", Dog.class);
      System.out.println(dog);
      System.out.println("-------容器关闭阶段---------");
      // 手动关闭容器(触发Bean的销毁流程)
      ac.close(); // 注意:ApplicationContext接口无close方法,需使用其子类ClassPathXmlApplicationContext
    }
}</pre></div>
<p class="maodian"></p><h3>2. 测试结果与分析</h3>
<p>控制台输出如下(结合注解方式和后置处理器):</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202601/2026011314405652.png" /></p>
<p>输出结果完全匹配我们之前拆解的生命周期阶段,验证了流程的正确性。</p>
<p class="maodian"></p><h2>六、核心知识点总结(面试必背)</h2>
<ul><li>Spring Bean生命周期8阶段:创建 &rarr; 注入 &rarr; 初始化前 &rarr; 初始化 &rarr; 初始化后 &rarr; 就绪 &rarr; 销毁 &rarr; 容器关闭;</li><li>生命周期回调3种实现方式及优先级:注解(@PostConstruct/@PreDestroy)&gt; 接口(InitializingBean/DisposableBean)&gt; XML(init-method/destroy-method);</li><li>Bean后置处理器作用:全局拦截所有Bean的初始化前后阶段,实现增强逻辑,是AOP的基础;</li><li>开发建议:优先使用注解方式实现回调,低耦合、高效率;避免使用接口方式,减少与Spring框架的耦合。</li></ul>
<p class="maodian"></p><h2>七、LomBok</h2>
<p>通过本文的讲解,相信大家已经对Spring Bean的生命周期有了全面且深入的理解。建议结合文中的代码案例实际运行测试,通过输出结果加深对各阶段的记忆,面试时才能做到游刃有余!</p>
<p>到此这篇关于深度解析Spring Bean生命周期以及LomBok插件的文章就介绍到这了,更多相关Spring Bean生命周期内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Spring&nbsp;Bean&nbsp;中的生命周期和获取方式详解</li><li>SpringBoot中Bean生命周期自定义初始化和销毁方法详解</li><li>Spring的Bean生命周期之BeanDefinition详解</li><li>SpringBoot中操作Bean的生命周期的方法总结</li><li>Spring中Bean的生命周期实例解析</li><li>Lombok&nbsp;报错:无法访问&nbsp;jdk.compiler&nbsp;内部类的解决方案</li><li>java中Lombok的实现示例</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 深度解析Spring Bean生命周期以及LomBok插件