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种外部化配置,此时你应该问自己:现在你可能记得,一周以后呢?一个月以后呢?所以你需要另辟蹊径,那就持续关注我吧😄

相关文章
|
7天前
|
存储 编译器 程序员
【C++学习】类和对象(中)一招带你彻底了解六大默认成员函数
【C++学习】类和对象(中)一招带你彻底了解六大默认成员函数
|
8月前
|
存储 Java
i++和++i傻傻分不清楚?这里给你最清楚的解答
i++和++i傻傻分不清楚?这里给你最清楚的解答
i++和++i傻傻分不清楚?这里给你最清楚的解答
|
编译器 C++
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(3)
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(3)
62 0
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(3)
|
编译器 C++
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(1)
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(1)
85 0
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(1)
|
编译器 C++
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(2)
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(2)
66 0
【C++】—— 类和对象(中)一张图带你搞清楚6个默认成员函数+万字总结 复习全靠它(2)
|
编译器 C++
<C++>一篇文章搞懂类和对象中常函数和常对象的实质以及避免空指针访问的小妙招
<C++>一篇文章搞懂类和对象中常函数和常对象的实质以及避免空指针访问的小妙招
107 0
|
XML 自动驾驶 Java
「控制反转」和「依赖倒置」,傻傻分不清楚?
- 控制反转(IoC)是什么?「反转」到底反转了什么?- Spring和IOC之间是什么关系?- 依赖注入(DI)和依赖倒置原则(DIP)又是什么?- IOC、DI和DIP有什么关系?
「控制反转」和「依赖倒置」,傻傻分不清楚?
|
Java 数据库连接 API
用这种方式实现单例,绝对能加分!
单例这个东西,可是说是Java基础面试必考问题,不管大小公司,提问率极高,有的面试官甚至直接让你写出具体的代码实现。所以,搞清楚单例的实现并且懂得接下来所说的,绝对能够让面试官对你有更好的印象。
|
Java 中间件 程序员
static关键字真能提高Bean的优先级吗?答:真能(上)
static关键字真能提高Bean的优先级吗?答:真能(上)
static关键字真能提高Bean的优先级吗?答:真能(上)
|
Java Spring
static关键字真能提高Bean的优先级吗?答:真能(中)
static关键字真能提高Bean的优先级吗?答:真能(中)