Spring的Bean有序吗?试试用@DependsOn或static来提高优先级(下)

简介: Spring的Bean有序吗?试试用@DependsOn或static来提高优先级(下)

static使用在Class内部类上


PersonConfig里增加一个静态内部类:


@Configuration(proxyBeanMethods = false)
public class PersonConfig {
  ... // 同上
  // 非静态内部类
    @Configuration(proxyBeanMethods = false)
    private class InnerClass {
        public InnerClass() {
            System.out.println("内部配置类InnerClass构造器被执行...");
        }
        @Bean
        public Person innerPerson() {
            System.out.println("@Bean -> innerPerson执行...");
            return new Person();
        }
    }
  // static静态内部类
    @Configuration(proxyBeanMethods = false)
    private static class StaticInnerClass {
        public StaticInnerClass() {
            System.out.println("静态内部配置类StaticInnerClass构造器被执行...");
        }
        @Bean
        public Person staticInnerPerson() {
            System.out.println("@Bean -> staticInnerPerson执行...");
            return new Person();
        }
    }
}


其它不变,再次运行测试程序,控制台输出:

...
配置类Config构造器被执行...
配置类PersonConfig构造器执行...
@Bean -> family执行...
@Bean -> staticFamily执行...
静态内部配置类StaticInnerClass构造器被执行...
@Bean -> staticInnerPerson执行...
内部配置类InnerClass构造器被执行...
@Bean -> innerPerson执行...
@Bean -> son执行...
@Bean -> father执行...


结论:


@Configuration(外层)配置类的初始化顺序依旧是按照AnnotationConfigApplicationContext的定义顺序来的

对于内部类的@Configuration的初始化(不管是静态还是非静态),也依旧是外部的@Configuration完成后才行

内部类里的@Bean的优先级均高于外层定义的@Bean,同时可以看到static静态内部类能够提升优先级,它比非静态内部类的优先级还高

内部类有限原则它只作用于本@Configuration类,也就是说仅在本主类内提升优先级。另外若出现多个内部类,按照定义顺序执行(static永远高于非static哦)

内部类的访问权限无所谓,private都行。


Spring Boot环境


在Spring Boot下会更加关心配置类和@Bean的执行顺序:因为Spring Boot内置了非常多的@Configuration以及@Bean,均是通过扫描的方式“收集”而不能Diy控制,因此它需要提供指定配置类顺序的能力。


控制@Configuration配置类顺序


关于Spring Boot下控制@Configuration的顺序,我们会使用@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder这三个注解去控制,关于它们的正确使用姿势,请参阅:你了解Spring Boot的自动配置吗?为何我的@AutoConfigureBefore注解不生效?


通过static提升优先级的示例


在Spring Boot的自动配置里,有非常多的通过static提升优先级的case,这里我找了个熟悉的例子进行说明:


@Configuration(proxyBeanMethods = false)
public class FeignClientsConfiguration {
  @Bean
  @Scope("prototype")
  @ConditionalOnMissingBean
  public Feign.Builder feignBuilder(Retryer retryer) {
    return Feign.builder().retryer(retryer);
  } 
  // 当Classpath里存在HystrixCommand、HystrixFeign等类时,就自动和Hystrix集成
  @Configuration(proxyBeanMethods = false)
  @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
  protected static class HystrixFeignConfiguration {
    @Bean
    @Scope("prototype")
    @ConditionalOnMissingBean
    @ConditionalOnProperty(name = "feign.hystrix.enabled")
    public Feign.Builder feignHystrixBuilder() {
      return HystrixFeign.builder();
    }
  }
}


这是一个典型案例:当然类路径存在Hystrix时,自动使用带有熔断功能的HystrixFeign.builder构建器,否则使用的默认的Feign.builder构建器。此处利用的就是内部类具有更高优先级,因此可以先去执行判断~


控制@Bean顺序


同Spring Framwork。

@DependsOn和static提升优先级的区别


其实把他俩放在一起比较其实蛮牵强的,根本不是同一回事嘛。但是在提升优先级方面,此处絮叨两句:


  1. @DependsOn强调的是Bean与Bean之间的依赖关系。如:A @DependsOn B表示,只有当B初始化完成了才会去初始化A。这里所谓的Bean可以是任何Bean:包括@Bean、@Component、@Configuration等一切形式
  2. static它主要运用在@Configuration配置文件内来提升优先级,这种优先级体现在:内部类里的@Bean比外部类会先加载,static静态内部类的@Bean又会比普通内部类的@Bean先加载


总结


本文主要讲解了Spring、Spring Boot中对配置文件以及Bean的加载顺序问题,虽说我们并不能绝对的控制Bean的顺序,但我们能采取一定的措施,如使用@DependsOn或static来提高某些Bean的优先级或者相对顺序,这便也能解决我们的需求。在实际使用中,我们的确并不需要控制每个Bean的顺序,而只需操控其相对顺序即可。


有的人说不能控制Bean的顺序是Spring容器在设计时疏忽的一点(究其原因是底层使用了Set的结构,因此无法保证顺序),我也在一定程度上表示赞同。但是它提供了形如@Order、@DependsOn、static来“补救”,我觉得这个“小缺点”已然无伤大雅了。


当然,这并不能算作Spring设计上的缺陷。但是它的底层存储如果使用更为抽象的Collection我觉得是更好的选择,你认为呢?

相关文章
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
7天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
13 1
|
2月前
|
XML Java 数据格式
Spring从入门到入土(bean的一些子标签及注解的使用)
本文详细介绍了Spring框架中Bean的创建和使用,包括使用XML配置文件中的标签和注解来创建和管理Bean,以及如何通过构造器、Setter方法和属性注入来配置Bean。
75 9
Spring从入门到入土(bean的一些子标签及注解的使用)
|
2月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
3月前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
239 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
3月前
|
XML Java 数据格式
spring复习02,xml配置管理bean
详细讲解了Spring框架中基于XML配置文件管理bean的各种方式,包括获取bean、依赖注入、特殊值处理、属性赋值、集合类型处理、p命名空间、bean作用域及生命周期和自动装配。
spring复习02,xml配置管理bean
|
2月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细解析Spring Bean的生命周期及其核心概念,并深入源码分析。Spring Bean是Spring框架的核心,由容器管理其生命周期。从实例化到销毁,共经历十个阶段,包括属性赋值、接口回调、初始化及销毁等。通过剖析`BeanFactory`、`ApplicationContext`等关键接口与类,帮助你深入了解Spring Bean的管理机制。希望本文能助你更好地掌握Spring Bean生命周期。
117 1
|
2月前
|
Java Spring
获取spring工厂中bean对象的两种方式
获取spring工厂中bean对象的两种方式
46 1
|
2月前
|
Java 开发者 Spring
Spring bean的生命周期详解!
本文详细介绍了Spring框架中的核心概念——Spring Bean的生命周期,包括实例化、属性赋值、接口回调、初始化、使用及销毁等10个阶段,并深入剖析了相关源码,如`BeanFactory`、`DefaultListableBeanFactory`和`BeanPostProcessor`等关键类与接口。通过理解这些核心组件,读者可以更好地掌握Spring Bean的管理和控制机制。
94 1
|
3月前
|
XML Java 数据格式
spring复习03,注解配置管理bean
Spring框架中使用注解配置管理bean的方法,包括常用注解的标识组件、扫描组件、基于注解的自动装配以及使用注解后的注意事项,并提供了一个基于注解自动装配的完整示例。
spring复习03,注解配置管理bean