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 { @Resource
UserServiceBean 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>
在各构造函数中加入日志输出可发现,会按照顺序依次加载。如下图所示:
- 如果我们在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 );
}
}
```
这个时候观察加载的顺序如下图所示:
- 在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注入函数, 将其存入静态变量.
*/
@Override
public 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)
Spring Boot 学习系列(09)—自定义Bean的顺序加载的更多相关文章
- Spring Boot 学习系列(05)—自定义视图解析规则
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 自定义视图解析 在默认情况下Spring Boot 的MVC框架使用的视图解析ViewResolver类是C ...
- Spring Boot 学习系列(08)—自定义servlet、filter及listener
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的filter及listener配置 在传统的Java web项目中,servlet.filter和li ...
- Spring boot 学习笔记 1 - 自定义错误
Spring Boot提供了WebExceptionHandler一个以合理的方式处理所有错误的方法.它在处理顺序中的位置就在WebFlux提供的处理程序之前,这被认为是最后一个处理程序. 对于机器客 ...
- Spring Boot 学习系列(03)—jar or war,做出你的选择
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 两种打包方式 采用Spring Boot框架来构建项目,我们对项目的打包有两种方式可供选择,一种仍保持原有的 ...
- Spring Boot 学习系列(07)—properties文件读取
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 传统的properties读取方式 一般的,我们都可以自定义一个xxx.properties文件,然后在工程 ...
- Spring Boot 学习系列(10)—SpringBoot+JSP的使
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 解决问题 随着spring boot 框架的逐步使用,我们期望对于一些已有的系统进行改造,做成通用的脚手架, ...
- Spring Boot 学习系列(06)—采用log4j2记录日志
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 为什么选择log4j2 log4j2相比于log4j1.x和logback来说,具有更快的执行速度.同时也支 ...
- Spring Boot 学习系列(01)—从0到1,只需两分钟
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 快速构建 如果我们想基于spring mvc 提供一个简单的API查询服务,传统的方式,首先需要我们引入sp ...
- Spring Boot 学习系列(序)—Spring Boot
此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. Spring Boot? Spring Boot 是由pivotal团队提供的一个基于Spring的全新框架 ...
随机推荐
- 【ZZ】Visual C++ 6.0 精简安装版(支持VA、ICC 等等安装)
(2012-04-22 08:10:10) 标签: it 分类: 软件_Software Visual C++ 6.0 精简安装版(支持VA.ICC 等等安装) 2012-04-16 21:07 想找 ...
- Selenium学习(一)环境搭建
一.安装selenium有两种方式: 1.pip install -U selenium(网络条件好) 2.下载selenium安装包,通过python setup.py install(压缩包)或p ...
- 带缓冲的IO( 标准IO库 )
前言 在之前,学习了 read write 这样的不带缓冲IO函数.而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 writ ...
- HUD 2031: 进制转换
进制转换 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- Microsoft Visual Studio 2013 已停止工作的解决方法
VS最近莫名奇妙老师崩溃,每次只能修复以后才能正常使用, 后参考 http://www.jb51.net/softjc/226465.html 网页的介绍, 恍然:之前使用OSchina GIT 服务 ...
- EasyDarwin Streaming Server对Task的调用方法
我们在EasyDarwin流媒体服务器的二次开发过程中,经常会需要定义自己的Task类,例如在EasyDarwin中,RTSPSessioin.HTTPSession.RTCPTask等,都是Task ...
- Java HotSpot(TM) 64-Bit Server VM warning: Insufficient space for shared memory file...
Java HotSpot(TM) 64-Bit Server VM warning: Insufficient space for shared memory file: 把tomcat中的日志删除, ...
- ecshop属性排序
属性的排序有三个方式:sort_order, attr_price, goods_attr_id如果要修改的话,修改 includes/lib_goods.php文件的 get_goods_prope ...
- IDEA eclipse 控制台日志输出到文件
eclipse IDEA
- php设计模式之单例模式实例(设计mysqli连接数据的数据处理类)
一直在研究php的设计模式,但是没有亲历使用过,所以还是一知半解,通过几天的学习终于对php的单例设计模式稍稍的有些了解,特此写出一个数据库处理类(只涉及到简单的原理),以便自己以后方便查阅,至于其他 ...