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

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

方案二(推荐):使用@DependsOn


Spring提供了一个@DependsOn注解,能够解决这类问题。这个场景的核心思想是:猫(监听者)必须确保在主人(事件发送者)放鱼(发送事件动作)之前完成实例化且注册监听,这样才不会错过每一条鱼。所以我们可以这么做(依旧基于原Config.java文件做出修改):


@Configuration(proxyBeanMethods = false)
public class Config {
    // @DependsOn // 若里面不写值,该注解无效。但若写了值,请确保里面的Bean都有,否则报错
    @DependsOn({"cc", "tom"})
    @Bean
    public MasterBean master() {
        return new MasterBean();
    }
    @Bean
    public Cat tom() {
        Cat tom = new Cat("Tom");
        Master.getMaster().addObserver(tom);
        return tom;
    }
    @Bean
    public Cat cc() {
        Cat cc = new Cat("Cc");
        Master.getMaster().addObserver(cc);
        return cc;
    }
}


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


...
10:04:10.729 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'config'
10:04:10.736 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'cc'
10:04:10.741 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'tom'
10:04:10.741 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'master'
YoutBatman主人放了一条鱼,通知猫过来吃~~~~~~
Tom吃了主人YoutBatman放的鱼
Cc吃了主人YoutBatman放的鱼
YoutBatman主人放了一条鱼,通知猫过来吃~~~~~~
Tom吃了主人YoutBatman放的鱼
Cc吃了主人YoutBatman放的鱼
YoutBatman主人放了一条鱼,通知猫过来吃~~~~~~
Tom吃了主人YoutBatman放的鱼
Cc吃了主人YoutBatman放的鱼


完美。这种处理方式是被推荐的方式,它能显示的控制Bean的依赖关系,而不受到其它影响,是值得信赖的使用方式。


说明:在“编程界”有个设计原则:显示的指出往往比隐式的更好,更稳定和更具表达力


方案三(不推荐):使用@Lazy


使用@Lazy只是一种曲线的解决方案,有些case它并不适合,因此并不推荐。


场景二示例:


这种场景在纯Spring环境下我们几乎遇不见,缘由是在Spring下所有的配置文件都是我们手动确定和编写,所以“哪些能写、哪些不能写,哪些在前,哪些在后”均是确定的,由我们程序员自行控制。该场景在Spring Boot场景下被大量用到,下面会举例说明。


当然,即使到了Spring Boot下,此部分初始化原理依旧是Spring Framwork的,因此这里也不闲着,通过代码示例来展示其加载顺序,核心便是介绍static关键字的使用。


使用static提升Bean的优先级


static代表静态,标注在类上表示该类是静态(内部)类,标注在方法上表示该方法是属于类的静态方法(不需要实例化即可调用),“看起来”可以是可以提升优先级的,那么实际如何呢?不能臆断,且看下面示例


static使用在@Bean方法上


准备两个配置类:


@Configuration(proxyBeanMethods = false)
public class PersonConfig {
    public PersonConfig() {
        System.out.println("配置类PersonConfig构造器执行...");
    }
    @Bean
    public Person son() {
        System.out.println("@Bean -> son执行...");
        return new Person("YourBatman-son", 18);
    }
    @Bean
    public Person father() {
        System.out.println("@Bean -> father执行...");
        return new Person("YourBatman", 48);
    }
}
@Configuration(proxyBeanMethods = false)
public class Config {
    public Config() {
        System.out.println("配置类Config构造器被执行...");
    }
    @Bean
    public Family family() {
        System.out.println("@Bean -> family执行...");
        return new Family();
    }
    @Bean
    public static Family staticFamily() {
        System.out.println("@Bean -> staticFamily执行...");
        return new Family();
    }
}


书写测试程序:

public static void main(String[] args) {
    new AnnotationConfigApplicationContext(Config.class, PersonConfig.class);
}


运行程序,控制台打印:


/

配置类Config构造器被执行...
配置类PersonConfig构造器执行...
@Bean -> family执行...
@Bean -> staticFamily执行...
@Bean -> son执行...
@Bean -> father执行...


结论:


  1. @Configuration配置类最优先被初始化,才会继续初始化其里面的@Bean
  2. 若有多个 @Configuration配置类,顺序由你构造AnnotationConfigApplicationContext时传入的顺序为准(若是被scan扫描进去的,则无序)
  3. @Bean方法上加static成为静态方法,并不能提升此Bean的优先级
  4. 主要是因为@Bean的解析,必须是发生在@Configuration配置类被实例化后,因此它并不能提升优先级



相关文章
|
5月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 > Java系统属性 > application.properties > application.yml > application.yaml。
1022 0
|
10月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
774 26
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
364 12
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
507 12
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
848 4
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
394 6
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
495 4
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
301 1
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。