static关键字真能提高Bean的优先级吗?答:真能(下)

简介: static关键字真能提高Bean的优先级吗?答:真能(下)

解决方案:static关键字提升优先级


AppConfig:
//@Bean
//BeanFactoryPostProcessor postProcessor() {
//    return new MyBeanFactoryPostProcessor();
//}
@Bean
static BeanFactoryPostProcessor postProcessor() {
    return new MyBeanFactoryPostProcessor();
}


运行程序,结果输出:


MyBeanFactoryPostProcessor init...
AppConfig init...
son init...hashCode() = 1906549136
Parent init...
// @PostConstruct注解生效喽
AppConfig.parent = com.yourbatman.bean.Parent@baf1bb3
...


世界一下子又清爽了有木有。


原因总结


以上三个case是有共同点的,粗略的讲导致它们的原因甚至是同一个:AppConfig这个Bean被过早初始化。然而我们的解决方案似乎也是同一个:使用static提升Bean的优先级。


那么为何AppConfig会被提前初始化呢?为何使用static关键字就没有问题了呢?根本原因可提前剧透:static静态方法属于类,执行静态方法时并不需要初始化所在类的实例;而实例方法属于实例,执行它时必须先初始化所在类的实例。听起来是不是非常的简单,JavaSE的东西嘛,当然只知晓到这个层次肯定是远远不够的,限于篇幅原因,关于Spring是如何处理的源码级别的分析我放在了下篇文章,请别走开哟~


static静态方法一定优先执行吗?


看完本文,有些小伙伴就忍不住跃跃欲试了,甚至很武断的得出结论:static标注的@Bean方法优先级更高,其实这是错误的,比如你看如下示例:


@Configuration
class AppConfig2 {
    AppConfig2(){
        System.out.println("AppConfig2 init...");
    }
    @Bean
    Son son() {
        return new Son();
    }
    @Bean
    Daughter daughter() {
        return new Daughter();
    }
    @Bean
    Parent Parent() {
        return new Parent();
    }
}


运行程序,结果输出:


AppConfig2 init...
son init...
Daughter init...
Parent init...

这时候你想让Parent在Son之前初始化,因此你想着在用static关键字来提升优先级,这么做:


AppConfig2:
//@Bean
//Parent Parent() {
//    return new Parent();
//}
@Bean
static Parent Parent() {
    return new Parent();
}


结果:你徒劳了,static貌似并没有生效,怎么回事?


原因浅析


为了满足你的好奇心,这里给个浅析,道出关键因素。我们知道@Bean方法(不管是静态方法还是实例方法)最终都会被封装进ConfigurationClass实例里面,使用Set<BeanMethod> beanMethods存储着,关键点在于它是个LinkedHashSet所以是有序的(存放顺序),而存入的顺序底层是由clazz.getDeclaredMethods()来决定的,由此可知@Bean方法执行顺序和有无static没有半毛钱关系。


image.png


说明:clazz.getDeclaredMethods()得到的是Method[]数组,是有序的。这个顺序由字节码(定义顺序)来保证:先定义,先服务。


由此可见,static并不是真正意义上的提高Bean优先级,对于如上你的需求case,你可以使用@DependsOn注解来保证,它也是和Bean顺序息息相关的一个注解,在本专栏后续文章中将会详细讲到。


所以关于@Bean方法的执行顺序的正确结论应该是:在同一配置类内,在无其它“干扰”情况下(无@DependsOn、@Lazy等注解),@Bean方法的执行顺序遵从的是定义顺序(后置处理器类型除外)。


小提问:如果是垮@Configuration配置类的情况,顺序如何界定呢?那么这就不是同一层级的问题了,首先考虑的应该是@Configuration配置类的顺序问题,前面有文章提到过配置类是支持有限的的@Order注解排序的,具体分析请依旧保持关注A哥后续文章详解哈…


static关键字使用注意事项


在同一个@Configuration配置类内,对static关键字的使用做出如下说明,供以参考:


  1. 对于普通类型(非后置处理器类型)的@Bean方法,使用static关键字并不能改变顺序(按照方法定义顺序执行),所以别指望它
  2. static关键字一般有且仅用于@Bean方法返回为BeanPostProcessor、BeanFactoryPostProcessor等类型的方法,并且建议此种方法请务必使用static修饰,否则容易导致隐患,埋雷


static关键字不要滥用(其实任何关键字皆勿乱用),在同一配置类内,与其说它是提升了Bean的优先级,倒不如说它让@Bean方法静态化从而不再需要依赖所在类的实例即可独立运行。另外我们知道,static关键还可以修饰(内部)类,那么如果放在类上它又是什么表现呢?同样的,你先思考,下篇文章我们接着聊~


说明:使用static修饰Class类在Spring Boot自动配置类里特别特别常见,所以掌握起来很具价值


思考题:


今天的思考题比较简单:为何文首三种case的警告信息都是info级别呢?是否有级别过低之嫌?


总结


本文还是蛮干的哈,不出意外它能够帮你解决你工程中的某些问题,排除掉一些隐患,毕竟墨菲定律被验证了你担心的事它总会发生,防患于未然才能把自己置于安全高地嘛。


你可能诧异,A哥竟能把static关键字在Spring中的应用都能写出个专栏出来,是的,这不是就是本公众号的定位么 ,小而美和拒绝浅尝辄止嘛。对于一些知识(比如本文的static关键字的使用)我并不推崇强行记忆,因为那真的很容易忘,快速使用可以简单记记,但真想记得牢(甚至成为永久记忆),那必须得去深水区看看。来吧,下文将授之以渔~


很多小伙伴去强行记忆Spring Boot支持的那17种外部化配置,此时你应该问自己:现在你可能记得,一周以后呢?一个月以后呢?所以你需要另辟蹊径,那就持续关注我吧😄

相关文章
|
1月前
|
Java 编译器 程序员
Java多态背后的秘密:动态绑定如何工作?
本文介绍了Java中多态的实现原理,通过动态绑定和虚拟方法表,使得父类引用可以调用子类的方法,增强了代码的灵活性和可维护性。文中通过具体示例详细解析了多态的工作机制。
43 4
|
6月前
|
存储 编译器 程序员
【C++学习】类和对象(中)一招带你彻底了解六大默认成员函数
【C++学习】类和对象(中)一招带你彻底了解六大默认成员函数
|
存储 编译器 C++
C++继承和多态核心重点知识刨析,一文必拿下
C++继承和多态核心重点知识刨析,一文必拿下
C++继承和多态核心重点知识刨析,一文必拿下
|
缓存 安全 Java
12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路
12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路
113 0
12000+字Java反射,一起全面了解Java反射机制,为学习框架铺路
|
Java Maven
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
|
Java 中间件 程序员
static关键字真能提高Bean的优先级吗?答:真能(上)
static关键字真能提高Bean的优先级吗?答:真能(上)
static关键字真能提高Bean的优先级吗?答:真能(上)
|
Java
编写Java程序,中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝参见玉帝,而每一天参
编写Java程序,中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝参见玉帝,而每一天参
253 0
编写Java程序,中国道教中掌管天宫的最高权力统治者是玉帝(Emperor),我们可以认为玉帝是一个单例模式,在这个场景中,有玉帝和天宫的大臣(Minister)们,大臣每天要上朝参见玉帝,而每一天参
|
Java 数据库连接 API
用这种方式实现单例,绝对能加分!
单例这个东西,可是说是Java基础面试必考问题,不管大小公司,提问率极高,有的面试官甚至直接让你写出具体的代码实现。所以,搞清楚单例的实现并且懂得接下来所说的,绝对能够让面试官对你有更好的印象。
|
Java Spring
static关键字真能提高Bean的优先级吗?答:真能(中)
static关键字真能提高Bean的优先级吗?答:真能(中)
|
存储 安全 Java
static关键字真能提高Bean的优先级吗?答:真能
一个static关键字在Spring的使用,竟能写出一个专栏
677 0
static关键字真能提高Bean的优先级吗?答:真能