一个人的价值体现在能够帮助多少人。比如自己编码好,价值能得到很好的体现。如果你做出来的东西能够帮助别人开发,大大减少开发的时间,那么就功德无量。 但任何决定都是一把双刃剑, 提示:Spring Boot的自动配置是通过@EnableAutoConfiguration这个注解驱动的,默认是开启状态。但你也可以通过 我们已然知道,在传统的 说明:这三个注解是Spring Boot提供的而非Spring Framwork。其中前两个是1.0.0就有了, 我们知道Spring对Bean的初始化其实是无序的,并不能通过 值得注意的是:Spring对Bean定义信息的收集是按照@Configuration配置文件的顺序来的,并且之前是隔离的。也就是说先收集完配置1里面所有的@Bean定义信息,才会继续收集配置2的。使用static提高优先级,有且仅在配置文件内部提高,出了配置文件后无效。 此处便以大家最为熟悉的WebMvc的自动配置场景为例: 在 这些都很容易理解:模版引擎必须在webMVC全部配置好后才开始配置。 说实话,针对这三个注解,实在有太多人把它进行误用了,想用但是用了却又不生效,于是就开始“骂娘”动作,这也是我书写本文的最大动力所在:纠正你的错误使用,告诉你正确姿势。 我见到的大多数小伙伴都这么来使用它:我这里使用“伪代码”进行模拟 启动Spring Boot容器,控制台打印: 这个时候你就想:让ParentConfig优先于SonConfig先执行(毕竟先有父母才有儿子嘛)。因此就想当然的这么干: 通过 what a fuck,顺序怎么还没有变呢?代码不会骗人, 针对这种case要想达到预期效果,你需要如下两步: 再次启动Spring Boot容器,打印输出: 完美。Parent终于在Son之前完成了初始化,也就是说我们的 所以对于 为了更好的辅助理解,加强记忆,本文将这三大注解解析时机简要的说一下,知道了它被解析的时机,自然就很好解释你心底的那个为什么:为什么我注解写在这里无效呢? 这三个注解的解析都是交给 这个排序的“解析”过程还是蛮复杂的,本文点到为止,观其大意即可。此排序器被连个地方使用到: 综上解析时机,你可以简单粗暴的记住结论: 关于Spring Boot自动配置顺序相关的三大注解 我看到不少文章、生产代码都使用错了(估计有没有效果自己的都不知道,又或者刚好确实是在xxx后面执行而以为生效了),希望本文能帮助到你。 原创不易,码字不易,多谢你的、、关注。
目录
前言
Spring Boot
是Spring家族具有划时代意义的一款产品,它发展自Spring Framwork
却又高于它,这种高于它主要表现在其最重要的三大特性,而其中最最最为重要的便是Spring Boot的自动配置(AutoConfiguration
)。与其说是自动,倒不如说是智能,该框架看起来好像“更聪明”了。Spring Boot
的出现解决了程序员,让开发效率可以指数级提升。然后它带来的问题也是因为它的太智能,使得倘若出了问题就会让众多程序员两眼一抹黑,无从下手。这不,本文将要讨论的是Spring Boot
提供给我们的几个注解:@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
标注在了配置文件上,为何不生效的问题。spring.boot.enableautoconfiguration = false
来关闭它,回退到Spring Framwork时代。
正文
Spring Framwork
里,一个@Configuration
标注的类就代表一个配置类,当存在多个@Configuration
时,他们的执行顺序是由使用者手动指定的:构造ApplicationContext
传入的顺序就是执行顺序。那么到了Spring Boot下,这一切都变成自动的了,怎么办?如何控制配置的先后顺序呢?还好,Spring Boot给我们提供了@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
这三个注解旨在帮我们解决这种需求。@AutoConfigureOrder
属于1.3.0版本新增的注解,表示绝对顺序(数字越小,优先级越高)。另外,这几个注解并不互斥,可以同时标注在同一个@Configuration
自动配置类上
配置类为何需要顺序?
@Order
注解指定顺序值来排序。而对于配置类来说,很多场景下对配置类的执行顺序是必须的,因为前后的Bean(定义)之前存在依赖关系,有且仅当某个前面的加载完成(并不代表初始化完成)后,后面的判断才会有意义,所以需要通过这三大注解来辅助实现这种需求。
Spring Boot内置的配置顺序case举例
@Configuration(proxyBeanMethods = false) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { ... } @Configuration(proxyBeanMethods = false) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { ... } @Configuration(proxyBeanMethods = false) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) public class ServletWebServerFactoryAutoConfiguration { ... }
WebMvcAutoConfiguration
执行初始化的条件是:DispatcherServletAutoConfiguration、TaskExecutionAutoConfiguration、ValidationAutoConfiguration
这三个哥们都已经完成初始化DispatcherServletAutoConfiguration
执行初始化的条件是:ServletWebServerFactoryAutoConfiguration
已经完成初始化ServletWebServerFactoryAutoConfiguration
执行初始化的条件是:@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
最高优先级,也就是说它无其它依赖,希望自己是最先被初始化的
DispatcherServletAutoConfiguration
和ServletWebServerFactoryAutoConfiguration
),那就按照相对顺序走
WebMvcAutoConfiguration
配置完成后,在它之后其实还有很多配置会尝试执行,例如:@AutoConfigureAfter(WebMvcAutoConfiguration.class) class FreeMarkerServletWebConfiguration extends AbstractFreeMarkerConfiguration { ... } @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class GroovyTemplateAutoConfiguration { ... } @AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class }) public class ThymeleafAutoConfiguration { ... } @AutoConfigureAfter(WebMvcAutoConfiguration.class) public class LifecycleMvcEndpointAutoConfiguration { ... }
使用误区(重点)
错误使用示例
@Configuration public class B_ParentConfig { B_ParentConfig() { System.out.println("配置类ParentConfig构造器被执行..."); } } @Configuration public class A_SonConfig { A_SonConfig() { System.out.println("配置类SonConfig构造器被执行..."); } } @Configuration public class C_DemoConfig { public C_DemoConfig(){ System.out.println("我是被自动扫描的配置,初始化啦...."); } } @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args).close(); } }
配置类SonConfig构造器被执行... 配置类ParentConfig构造器被执行... 我是被自动扫描的配置,初始化啦....
@AutoConfigureBefore(A_SonConfig.class) @Configuration public class B_ParentConfig { B_ParentConfig() { System.out.println("配置类ParentConfig构造器被执行..."); } }
@AutoConfigureBefore
控制,表示在A_SonConfig
之前执行此配置。语义上貌似没有任何问题,再次启动SB容器:配置类SonConfig构造器被执行... 配置类ParentConfig构造器被执行... 我是被自动扫描的配置,初始化啦....
@AutoConfigureBefore
的语义也没有问题,而是你使用的姿势不对,下面给你正确的使用姿势。
正确使用姿势
A_SonConfig
和B_ParentConfig
挪动到Application扫描不到的包内,切记:一定必须是扫描不到的包META-INF/spring.factories
,内容为:org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.fsx.autoconfig.A_SonConfig,com.fsx.autoconfig.B_ParentConfig
我是被自动扫描的配置,初始化啦.... 配置类ParentConfig构造器被执行... 配置类SonConfig构造器被执行...
@AutoConfigureBefore
注解生效了。当然针对此使用姿势并不是完全没有“副作用”的,有如下细节需要引起注意:
@AutoConfigureBefore
这个注解,想依赖于EnableAutoConfiguration
配置的来控制先后顺序,答案是不可以的,控制不了我是被自动扫描的配置,初始化啦....
这句话,然而可以发现被扫描进去(错误示例)时实例化是在它前面,而通过spring.factories
方式进去是在它的后面
Spring Boot
的自动配置均是通过spring.factories
来指定的,它的优先级是最低的(执行时机是最晚的)。扫描进来的一般都是你自己自定义的配置类,所以优先级是最高的:肯定在自动配置之前执行
org.springframework
这种包名,否则“天下大乱”(当然喽:Spring Boot也有一个类抓们处理防止你配置错了,具体参见ComponentScanPackageCheck
默认实现)spring.factories
配置了,否则后者会覆盖前者,容易造成出错的@AutoConfigureBefore
等三个注解的正确使用姿势是:请使用在你的自动配置里(一般是你自定义starter时使用),而不是使用在你业务工程中的@Configuration
里,毫无效果。
@AutoConfigureBefore三大注解解析时机浅析
AutoConfigurationSorter
来排序、处理的,类似于AnnotationAwareOrderComparator
去解析排序@Order
注解。class AutoConfigurationSorter { // 唯一给外部调用的方法:返回排序好的Names,因此返回的是个List嘛(ArrayList) List<String> getInPriorityOrder(Collection<String> classNames) { ... // 先按照自然顺序排一波 Collections.sort(orderedClassNames); // 在按照@AutoConfigureBefore这三个注解排一波 orderedClassNames = sortByAnnotation(classes, orderedClassNames); return orderedClassNames; } ... }
AutoConfigurationImportSelector
:Spring自动配置处理器,用于加载所有的自动配置类。它实现了DeferredImportSelector
接口:这也顺便解释了为何自动配置是最后执行的原因~AutoConfigurations
:表示自动配置@Configuration类。@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
这三个注解只能作用于自动配置类,而不能是自定义的@Configuration配置类。
总结
@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder
就先介绍到这了,本文用意主要是为了帮助大家规范此些“常用注解”的使用,规避一些误区,端正使用姿势,避免犯错又丈二和尚。
声明
把本文到你的朋友圈是被允许的,但拒绝抄袭
。你也可【左边扫码/或加wx:fsx641385712】邀请你加入我的 Java高工、架构师 系列群大家庭学习和交流。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算