spring的depends-on

本文详细介绍了Spring框架中Bean的依赖注入和初始化顺序。通过XML配置,使用`ref`属性实现Bean之间的依赖关系,如BeanOne、BeanTwo和BeanThree的依赖链。同时,展示了`depends-on`属性如何定义初始化顺序。在关闭容器时,Bean的销毁顺序与初始化相反,体现了Spring对Bean生命周期的管理。

1、一个bean对象依赖另一个bean依赖项,需要xml的ref来实现他们的依赖关系,也可以用depends-on来实现依赖关系。
2、要表示对多个bean的依赖关系,提供一个bean名称列表作为依赖属性的值(逗号、空格和分号是有效的分隔符):
3、依赖属性既可以指定初始化时依赖关系,也可以指定对应的销毁时依赖关系(仅在单例bean中)。因此,依赖还可以控制关闭顺序。
4、实例用ref来实现依赖关系:
(1) BeanOne 对象单独不依赖其他对象。

package com.it.app.bean;

import org.springframework.beans.factory.DisposableBean;

public class BeanOne implements DisposableBean {


    public BeanOne(){
        System.out.println("---BeanOne对象创建");
    }


    @Override
    public void destroy() throws Exception {
        System.out.println("---BeanOne对象正在销毁");
    }
}

(2)BeanTwo对象依赖于beanOne。

package com.it.app.bean;

import org.springframework.beans.factory.DisposableBean;

public class BeanTwo implements DisposableBean {

    private BeanOne beanOne;


    public BeanTwo(BeanOne beanOne){
        this.beanOne = beanOne;
        System.out.println("---BeanTwo对象创建");
    }


    @Override
    public void destroy() throws Exception {
        System.out.println("---BeanTwo对象正在销毁");
    }
}

(3)BeanThree对象依赖BeanTwo

package com.it.app.bean;

import org.springframework.beans.factory.DisposableBean;

public class BeanThree implements DisposableBean {

    private BeanTwo beanTwo;

    public BeanThree(BeanTwo beanTwo){
        this.beanTwo = beanTwo;
        System.out.println("---BeanThree对象创建");

    }

    @Override
    public void destroy() throws Exception {
        System.out.println("---BeanThree对象正在销毁");
    }
}

(4)xml文件配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">


    <bean id="beanOne" class="com.it.app.bean.BeanOne"></bean>
    <bean id="beanTwo" class="com.it.app.bean.BeanTwo">
        <constructor-arg ref="beanOne"></constructor-arg>
    </bean>
    <bean id="beanThree" class="com.it.app.bean.BeanThree">
        <constructor-arg ref="beanTwo"></constructor-arg>
    </bean>
</beans>

(5)容器启动初始化和关闭执行顺序:

package com.it.app;

import com.it.app.service.ServiceImpl4;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppTwo {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-contextTwo.xml");
        System.out.println("****spring容器已启动****");
        context.close();
        System.out.println("****spring容器已关闭****");

    }
}

(6) 依赖初始化和关闭执行顺序:
初始化:BeanOne–>BeanTwo–>BeanThree
关闭: BeanThree -->BeanTwo–>BeanOne
5、实例用depends-on来实现依赖关系:
(1) beanOne ,beanTwo,beanThree对象创建:

package com.it.app.bean;

import org.springframework.beans.factory.DisposableBean;

public class BeanOne implements DisposableBean {
    
    public BeanOne(){
        System.out.println("---BeanOne对象创建");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("---BeanOne对象正在销毁");
    }
}

package com.it.app.bean;

import org.springframework.beans.factory.DisposableBean;

public class BeanTwo implements DisposableBean {

    public BeanTwo(){
        System.out.println("---BeanTwo对象创建");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("---BeanTwo对象正在销毁");
    }
}
package com.it.app.bean;

import org.springframework.beans.factory.DisposableBean;

public class BeanThree implements DisposableBean {
    public BeanThree(){

        System.out.println("---BeanThree对象创建");

    }
    @Override
    public void destroy() throws Exception {
        System.out.println("---BeanThree对象正在销毁");
    }
}

xml信息,依赖关系:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">


<!--    <bean id="beanOne" class="com.it.app.bean.BeanOne"></bean>
    <bean id="beanTwo" class="com.it.app.bean.BeanTwo">
        <constructor-arg ref="beanOne"></constructor-arg>
    </bean>
    <bean id="beanThree" class="com.it.app.bean.BeanThree">
        <constructor-arg ref="beanTwo"></constructor-arg>
    </bean>-->
    <bean id="beanThree" class="com.it.app.bean.BeanThree" depends-on="beanTwo,beanOne"></bean>
    <bean id="beanTwo" class="com.it.app.bean.BeanTwo"></bean>
    <bean id="beanOne" class="com.it.app.bean.BeanOne"  ></bean>
</beans>

(2) 依赖初始化和关闭执行顺序:
初始化:BeanOne–>BeanTwo–>BeanThree
关闭: BeanOne -->BeanTwo–>BeanThree

<think>嗯,用户现在问的是Spring框架中的@DependsOn注解有什么用。我需要先回忆一下这个注解的功能和应用场景。记得在Spring中,Bean的默认初始化顺序是根据依赖关系自动决定的,但有时候可能需要手动指定某些Bean先初始化,这时候@DependsOn就派上用场了。 首先,用户可能已经了解Spring的基本概念,比如Bean和依赖注入,但可能在实际开发中遇到了Bean初始化顺序的问题。比如,某个Bean需要在另一个Bean初始化之后再初始化,即使它们之间没有直接的依赖关系。这时候@DependsOn可以显式指定这种顺序。 接下来,我需要考虑用户为什么会问这个问题。也许他们在项目中遇到了Bean初始化顺序导致的错误,或者看到别人代码中用了@DependsOn,想了解它的用途。需要解释清楚@DependsOn的作用,以及它和隐式依赖注入的区别。 然后,应该举几个具体的例子,比如数据库连接池和日志配置,或者事件发布者和监听器的例子,这样用户能更直观地理解。同时,要提到使用@DependsOn的注意事项,比如避免循环依赖,以及可能增加配置复杂度的问题。 还要注意用户之前的问题是关于Disruptor的学习曲线,涉及内存屏障和序列号机制,这可能意味着他们对底层机制和框架的内部工作原理感兴趣。所以在解释@DependsOn时,可以稍微提到Spring容器管理Bean生命周期的机制,但保持简洁明了。 最后,确保回答结构清晰,分点说明,并给出实际应用场景和示例代码,这样用户能逐步理解和应用这个注解。同时提醒用户不要滥用,优先考虑隐式依赖,只有在必要时才使用@DependsOn,以避免不必要的复杂性。</think>--- ### **Spring 的 `@DependsOn` 注解详解** #### **1. 核心作用** `@DependsOn` 用于 **显式指定 Bean 的初始化顺序**,确保某个 Bean 在另一个(或多个)Bean **初始化完成后再被创建**。它解决的是 Spring 容器默认依赖管理无法覆盖的特殊场景。 --- #### **2. 使用场景** ##### **场景 1:隐式依赖无法满足顺序要求** - **问题**:Bean A 和 Bean B 没有直接依赖关系(如 A 不直接调用 B 的方法),但 B 的初始化必须优先于 A(例如 B 是数据库连接池,A 是依赖数据库的组件)。 - **解决**:在 Bean A 上添加 `@DependsOn("b")`。 **示例**: ```java @Configuration public class AppConfig { @Bean @DependsOn("dataSource") // 确保数据库连接池先初始化 public ServiceA serviceA() { return new ServiceA(); } @Bean public DataSource dataSource() { return new HikariDataSource(); } } ``` ##### **场景 2:多 Bean 协作的初始化顺序** - **问题**:多个 Bean 需要在初始化时执行特定逻辑(如日志配置、环境检查),且这些逻辑必须按特定顺序执行。 - **解决**:通过 `@DependsOn` 定义链式依赖关系。 **示例**: ```java @Bean @DependsOn({"loggerInitializer", "configValidator"}) // 先初始化日志,再校验配置,最后初始化服务 public MainService mainService() { return new MainService(); } ``` ##### **场景 3:避免循环依赖导致初始化失败** - **问题**:Bean A 依赖 Bean B,同时 Bean B 又依赖 Bean A,形成循环依赖(Spring 默认会报错 `BeanCurrentlyInCreationException`)。 - **解决**:通过 `@DependsOn` 强制指定初始化顺序,打破循环。 --- #### **3. 使用方式** - **注解位置**:类级别或 `@Bean` 方法级别。 - **依赖多个 Bean**:用数组形式指定多个 Bean 名称,如 `@DependsOn({"bean1", "bean2"})`。 **示例**: ```java @Component @DependsOn("eventPublisher") // 确保事件发布者先初始化 public class EventListener { // 监听事件发布者的消息 } ``` --- #### **4. 底层机制** - **Spring 容器流程**: 1. 解析所有 Bean 的定义,构建依赖关系图。 2. 根据 `@DependsOn` 声明的依赖关系,调整 Bean 的初始化顺序。 3. 按顺序调用 Bean 的初始化方法(如 `@PostConstruct` 或 `InitializingBean` 接口)。 - **与隐式依赖的区别**: - **隐式依赖**:通过构造函数、Setter 方法或字段注入自动推导依赖关系。 - **显式依赖**:`@DependsOn` 不要求 Bean 之间有直接调用关系,仅控制初始化顺序。 --- #### **5. 注意事项** 1. **避免滥用**: - 优先通过隐式依赖(如构造函数注入)管理初始化顺序。 - 仅在无法通过依赖注入解决时使用 `@DependsOn`,避免代码复杂度增加。 2. **循环依赖风险**: - 若 `@DependsOn` 形成循环依赖链(如 A 依赖 B,B 依赖 A),Spring 会抛出 `BeanCreationException`。 3. **Bean 名称一致性**: - 依赖的 Bean 名称必须与容器中注册的名称一致(默认是类名首字母小写,或 `@Bean` 方法名)。 --- #### **6. 实际应用案例** **案例:事件发布者与监听器** - **需求**:事件监听器需在事件发布者初始化完成后注册,避免事件丢失。 - **代码**: ```java @Component @DependsOn("eventPublisher") // 确保事件发布者先初始化 public class OrderEventListener { @Autowired private EventPublisher eventPublisher; @PostConstruct public void registerListener() { eventPublisher.subscribe(this::handleOrderEvent); } } ``` --- ### **总结** `@DependsOn` 是 Spring 中用于 **显式控制 Bean 初始化顺序** 的工具,适用于依赖关系无法通过常规注入解决的场景。合理使用可以解决初始化顺序问题,但过度使用会导致配置臃肿。理解其原理后,可结合具体业务需求灵活选择隐式或显式依赖管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值