Spring高级注解之@DependsOn详解

 更新时间:2024年01月26日 08:46:37   作者:hy_coming  
这篇文章主要介绍了Spring高级注解之@DependsOn详解,@DependsOn注解可以定义在类和方法上,意思是我这个组件要依赖于另一个组件,也就是说被依赖的组件会比该组件先注册到IOC容器中,需要的朋友可以参考下

官方文档

Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization. A depends-on declaration can specify both an initialization-time dependency and, in the case of singleton beans only, a corresponding destruction-time dependency. Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. Thus, a depends-on declaration can also control shutdown order. May be used on any class directly or indirectly annotated with org.springframework.stereotype.Component or on methods annotated with Bean. Using DependsOn at the class level has no effect unless component-scanning is being used. If a DependsOn-annotated class is declared via XML, DependsOn annotation metadata is ignored, and <bean depends-on="..."/> is respected instead.

@DependsOn注解的作用

org.springframework.context.annotation.DependsOn该注解的属性是一个字符串数组,数组的元素是每个依赖的bean的名称。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
    String[] value() default {};
}

@DependsOn注解主要用于指定当前bean所依赖的beans。任何被指定依赖的bean都由Spring保证在当前bean之前创建。在少数情况下,bean不是通过属性或构造函数参数显式依赖于另一个bean,但却需要要求另一个bean优先完成初始化,则可以使用@DependsOn这个注解。

@DependsOn既可以指定初始化依赖顺序,也可以指定bean相应的销毁执行顺序(仅在单例bean的情况下)。

可用于任何直接或间接带@Component注解的bean或在用@Bean注释的方法上。 如果使用的是xml配置,则需要使用<bean dependens on=“…”/>标签.

简单描述就是@DependsOn可以控制bean的创建、初始化(InitializingBean)、销毁方法执行顺序。

示例:假如有三个Bean类叫Aaa、Bbb、Ccc分别实现了如下两个接口。org.springframework.beans.factory.InitializingBeanorg.springframework.beans.factory.DisposableBean

Ccc通过@DependsOn指定依赖bean创建的顺序为Bbb > Aaa

@DependsOn({"bbb","ccc"})
@Service
public class Aaa implements InitializingBean, DisposableBean {
 private static final Logger logger = LoggerFactory.getLogger(Aaa.class);
 public Aaa() {
  logger.info(this.getClass().getName() + " Construction");
 }
 @Override
 public void afterPropertiesSet() throws Exception {
  logger.info(this.getClass().getName() + " afterPropertiesSet");
 }
 @Override
 public void destroy() throws Exception {
  logger.info(this.getClass().getName() + " destroy");
 }
}

Bbb Ccc类实现如下

@Service
public class Bbb implements InitializingBean, DisposableBean {
 //实现和Aaa相同
}
@Service
public class Ccc implements InitializingBean, DisposableBean {
 //实现和Aaa相同
}

那么初始顺序如下: bbb --> ccc --> aaa

在这里插入图片描述

而销毁方法执行顺序正好相反如下: aaa --> ccc --> bbb

在这里插入图片描述

@DependsOn注解的实现原理

Spring在启动时扫描到一个bean,会封装成一个BeanDefinition,如果是AnnotatedBeanDefinition则解析类上的注解信息,发现@DependsOn注解,则读取value值,调用BeanDefinition#setDependsOn保存。 源码见ClassPathBeanDefinitionScanner#doScan,AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition, AnnotatedTypeMetadata)

创建bean时,也就是调用AbstractBeanFactory#doGetBean时,会获取这些被依赖的beanName,按照数组顺序,再调用AbstractBeanFactory#getBean(beanName)来优先创建被依赖的bean,从而达到控制依赖顺序。

除此之外,在创建bean时,还会调用AbstractBeanFactory#registerDisposableBeanIfNecessary来向Spring中注册带有销毁方法的bean,源码见DefaultSingletonBeanRegistry#registerDisposableBean,内部通过LinkedHashMap保存。key为bean名称。进程退出时,会逆序调用销毁方法。 源码见DefaultSingletonBeanRegistry#destroySingletons

public void destroySingletons() {
    if (logger.isTraceEnabled()) {
        logger.trace("Destroying singletons in " + this);
    }
    synchronized (this.singletonObjects) {
        this.singletonsCurrentlyInDestruction = true;
    }
    String[] disposableBeanNames;
    synchronized (this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }
    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
        destroySingleton(disposableBeanNames[i]);
    }
    this.containedBeanMap.clear();
    this.dependentBeanMap.clear();
    this.dependenciesForBeanMap.clear();
    clearSingletonCache();
}

到此这篇关于Spring高级注解之@DependsOn详解的文章就介绍到这了,更多相关@DependsOn详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java安全框架——Shiro的使用详解(附springboot整合Shiro的demo)

    Java安全框架——Shiro的使用详解(附springboot整合Shiro的demo)

    这篇文章主要介绍了Java安全框架——Shiro的使用详解,帮助大家更好的理解和学习使用Shiro,感兴趣的朋友可以了解下
    2021-04-04
  • java中int、double、char等变量的取值范围详析

    java中int、double、char等变量的取值范围详析

    这篇文章主要给大家介绍了关于java中int、double、char等变量取值范围的相关资料,每个变量都给出了详细的实例代码,对大家学习或者使用java具有一定的参考学习价值,需要的朋友可以参考下
    2021-10-10
  • Springboot详解如何整合使用Thymeleaf

    Springboot详解如何整合使用Thymeleaf

    这篇文章主要分享了Spring Boot整合使用Thymeleaf,Thymeleaf是新一代的Java模板引擎,类似于Velocity、FreeMarker等传统引擎,关于其更多相关内容,需要的小伙伴可以参考一下
    2022-06-06
  • Java的枚举,注解和反射(一)

    Java的枚举,注解和反射(一)

    今天小编就为大家分享一篇关于Java枚举,注解与反射原理说明,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-07-07
  • SpringBoot项目集成MinIO全过程

    SpringBoot项目集成MinIO全过程

    这篇文章主要介绍了SpringBoot项目集成MinIO全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • G1垃圾回收器在并发场景调优详解

    G1垃圾回收器在并发场景调优详解

    这篇文章主要为大家介绍了G1垃圾回收器在并发场景调优详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • Java实现MD5加密的方法

    Java实现MD5加密的方法

    这篇文章主要介绍了Java实现MD5加密的方法,实例分析了基于java实现md5加密的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • springcloud项目快速开始起始模板的实现

    springcloud项目快速开始起始模板的实现

    本文主要介绍了springcloud项目快速开始起始模板思路的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • Java catch与throw同时使用的操作

    Java catch与throw同时使用的操作

    这篇文章主要介绍了Java catch与throw同时使用的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 详细讲解Java中==与equals的区别对比

    详细讲解Java中==与equals的区别对比

    这篇文章主要为大家详细介绍了Java中==与equals的区别对比,文中有详细的代码示例供大家参考,具有一定的参考价值,感兴趣的同学可以参考阅读下
    2023-09-09

最新评论