Spring Boot 学习系列(09)—自定义Bean的顺序加载
此文已由作者易国强授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
Bean 的顺序加载
有些场景中,我们希望编写的Bean能够按照指定的顺序进行加载。比如,有UserServiceBean和OrderServiceBean,我们需要在OrderServiceBean中调用UserServiceBean,获取其提供的一些数据信息。针对这一场景,通常来说,有这么几种方式:
1、将UserServiceBean封装成一个服务类(如采用@Service注解),然后在OrderServiceBean中引入这个服务类,直接调用即可,简单快捷。示例如下所示:
@Service("userServiceBean") public class UserServiceBean { public String print() {System.out.println("this is UserServiceBean print"); return "print ok";}} @Service("orderServiceBean") public class OrderServiceBean { @ResourceUserServiceBean userServiceBean; public void invoke(){String ret = userServiceBean.print();System.out.println("this is OrderServiceBean invoke " + ret );}}
2、然而有些时候,我们的xxxServiceBean是没有封装成服务的,只是作为一个单纯的Bean注入到Spring容器中。这个时候如果我们需要使用这个Bean实例,通常会考虑直接从ApplicationContext中以getBean("xxxServiceBean")的方式获取。
在传统的项目中,我们一般都会在xml配置文件中注入xxxServiceBean,这个时候Spring容器会依据xml中代码编写的顺序依次加载各个Bean,示例如下所示:
<!-- 按代码编写顺序依次加载 --><!-- 订单服务Bean --><bean id="orderServiceBean" class="com.example.a.OrderServiceBean"></bean><!-- 演示服务--><bean id="depService" class="com.example.a.DepService"></bean><!-- 演示服务--><bean id="demoService" class="com.example.a.OtherDemoServiceImpl"></bean><!-- 用户服务Bean--><bean id="userServiceBean" class="com.example.a.UserServiceBean"></bean>
在各构造函数中加入日志输出可发现,会按照顺序依次加载。如下图所示:
![image](https://github.com/siyuyifang/image/blob/master/spring-boot/9/9-1.png?raw=true)- 如果我们在OrderServiceBean中有调用UserServiceBean,那么UserServiceBean则会优先于DepService和OtherDemoServiceImpl加载,调用代码如下:```public class OrderServiceBean {public OrderServiceBean() {System.out.println("OrderServiceBean constructor init.");UserServiceBean userServiceBean = SpringContextHolder.getBean("userServiceBean");String ret = userServiceBean.print();System.out.println("this is OrderServiceBean invoke " + ret ); } } ``` 这个时候观察加载的顺序如下图所示:![image](https://github.com/siyuyifang/image/blob/master/spring-boot/9/9-2.png?raw=true)- 在Spring Boot项目中,我们一般用@Configuration + @Bean注解的方式来替代xml中Bean的注入,这个时候定义Bean的加载顺序也很简单,在同一个配置类中,也是按照代码的编写顺序加载实例化的。示例如下所示:```@Configurationpublic class MyConfigs {@Bean("userServiceBean")public UserServiceBean userServiceBean(){ return new UserServiceBean(); }@Bean("orderServiceBean")public OrderServiceBean orderServiceBean(){ return new OrderServiceBean(); } ```
有这么一个使用场景,如果UserServiceBean 采用@Bean + @Configuration的方式注入,而OrderServiceBean采用@Service注解的形式提供服务,同时在OrderServiceBean中仍然通过ApplicationContext的getBean()方式获取UserServiceBean的示例,那么在编译时候会报如下错误:
其中SpringContextHolder.java的代码如下所示:
@Component("springContextHolder")public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; /*** 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.*/@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {SpringContextHolder.applicationContext = applicationContext;} /*** 取得存储在静态变量中的ApplicationContext.*/public static ApplicationContext getApplicationContext() {checkApplicationContext(); return applicationContext;} /*** 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.*/@SuppressWarnings("unchecked") public static <T> T getBean(String name) {checkApplicationContext(); return (T) applicationContext.getBean(name);} private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextUtil");}} }
这个时候,我们需要在OrderServiceBean类前加入如下注解,表示此Bean依赖于springContextHolder实例的加载,代码示例如下所示,再次编译通过。
@Service @DependsOn("springContextHolder")public class OrderServiceBean { public OrderServiceBean() {System.out.println("OrderServiceBean constructor init.");UserServiceBean userServiceBean = SpringContextHolder.getBean("userServiceBean");String ret = userServiceBean.print();System.out.println("this is OrderServiceBean invoke " + ret );}}
此外,如果需要指定一个Bean A 先于 Bean B加载,那么可以在Bean B类前加入@DependsOn("beanA"),指定依赖加载顺序。
不足之处,欢迎指正,谢谢~
免费体验云安全(易盾)内容安全、验证码等服务
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 如何能低成本地快速获取大量目标用户,而不是与竞争对手持久战?
【推荐】 小白用shiro(1)
转载于:https://www.cnblogs.com/163yun/p/9887317.html
Spring Boot 学习系列(09)—自定义Bean的顺序加载相关推荐
- Spring Boot 学习系列(08)—自定义servlet、filter及listener
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的filter及listener配置 在传统的Java web项目中,servlet.filter和li ...
- Spring Boot 学习系列(05)—自定义视图解析规则
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 自定义视图解析 在默认情况下Spring Boot 的MVC框架使用的视图解析ViewResolver类是C ...
- Spring Boot 学习系列(07)—properties文件读取
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的properties读取方式 一般的,我们都可以自定义一个xxx.properties文件,然后在工程 ...
- Spring Boot 学习系列(01)—从0到1,只需两分钟
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 快速构建 如果我们想基于spring mvc 提供一个简单的API查询服务,传统的方式,首先需要我们引入sp ...
- Spring Boot 学习系列(04)—分而治之,多module打包
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 明确功能,各司其职 在一个结构清晰的项目中,一个没有module划分的结构显然不是最佳实践.有人会说可以在同 ...
- Spring Boot : Spring Boot 开启 debug=true 查看哪些自动配置加载了
1.美图 2.概述 先看 自动配置原理 这里有个疑问?我们不能点开每个类,看看SpringBoot之Bean之条件注入@Condition 每个类上的注入条件是什么,而去人工的判断这个配置是否加载了. ...
- Vue+OpenLayers学习系列(十一)使用axios加载GeoServer发布的WFS服务
一.问题 1.之前用下面官网的方法 source.addFeatures() 将查询的图层信息加载到 source 里面,但是不知道为啥,死活出不来,也不报错,就很奇怪. var source = n ...
- Spring Boot 学习系列(02)—使用热部署,提升开发效
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 开发调试很简单 热部署的使用非常简单,但能极大的提高我们的开发效率,像传统的web应用,我们修改后需要重新编 ...
- Spring Boot干货系列:(二)配置文件解析
前言 上一篇介绍了Spring Boot的入门,知道了Spring Boot使用"习惯优于配置"(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)的理念让 ...
最新文章
- android 定时换图片,android 视频和图片切换并进行自动轮播
- 华为南太无线解决方案部梁旭阳_工业互联网产业联盟网络组走进华为南京研究所技术研讨会顺利召开...
- NetMarketShare:本月桌面浏览器市场份额几乎没有变化
- P2521 [HAOI2011]防线修建
- 前端(四)——CSS之导入方式、各类选择器
- Java并发编程的艺术,解读并发编程的优缺点
- Vue 进阶 (二)
- html5 网页宽度100,HTML5 Canvas 100%视口宽度?
- linux根目录9个g,linux根目录下5个主要的目录,及目录的功能
- 火影忍者 动漫 全集目录 分章节 精彩打斗剧集 思维导图整理
- python模拟勒索病毒
- java登录注册功能怎么实现_使用Java代码实现登录注册功能
- 读 Lars V. Ahlfors 之《复分析》
- RHCI 搭建 rhca 教室环境
- 【实验小技巧】github使用技巧
- Cadence Orcad建立批量原理图库(本地库.OLB)
- 电脑文件管理,教你批量给全部文件夹名称随机命名
- 吸引红杉资本中美两地基金联合领投,英国芯片企业Graphcore有何魔力?
- 【dtoj#4219】地中海气候
- JavaScript 有关获取当前/上个月/12个月前/七/7天/一周之前/下周一的日期格式 持续更新...
热门文章
- macos安装homebrew
- 一条 SQL 语句在 MySQL 中如何被执行的?
- *45.程序的装入方式
- SSH暴力破解IP大曝光
- 浅谈 Python 的 with 语句
- 158行代码!程序员复现DeepMind图像生成神器
- Fedora 30用dnf安装OpenCV及g++编译其应用程序
- 清华计算机知识工程怎么样,张民(muslv)清华大学计算机系知识工程组 硕士清华大学.ppt...
- linux的磁盘磁头瓷片作用,Linux 磁盘管理
- Uri跟Url的区别