Spring入门(六):条件化的bean
1. 概念
默认情况下,spring中定义的bean在应用程序启动时会全部装配,不管当前运行的是哪个环境(dev,qa或者prod),也不管当前运行的是什么系统(windows或者linux),但有些使用场景下,我们可能需要条件化的装配某些bean,即当满足某一条件时,装配某些bean,当不满足某一条件时,就忽略掉某些bean。
这个条件可以很简单,比如当某个jar包存在时,当存在某个环境变量时,也可以很复杂。
针对这个使用场景,spring中提供了@conditional
注解来实现条件化的bean。
2. 示例
为了更好的理解,我们通过具体的代码示例来理解下条件化的bean的实现方式。
由于windows系统和linux系统显示列表的命令不同,windows下是dir,linux下是ls,因此我们的需求是,应用程序启动时自动根据当前系统装配需要的bean,比如我的电脑系统是windows 7,那就只装配windows系统所需要的bean。
首先,定义一个接口listservice,该接口只包含一个方法showlistcmd:
package chapter03.conditional; public interface listservice { string showlistcmd(); }
然后定义该接口的2个实现类windowslistservice和linuxlistservice:
package chapter03.conditional; public class windowslistservice implements listservice { public windowslistservice() { system.out.println("this is windowslistservice constructor"); } @override public string showlistcmd() { return "dir"; } }
package chapter03.conditional; public class linuxlistservice implements listservice { public linuxlistservice() { system.out.println("this is linuxlistservice constructor"); } @override public string showlistcmd() { return "ls"; } }
然后分别定义windows系统和linux系统的判断条件:
package chapter03.conditional; import org.springframework.context.annotation.condition; import org.springframework.context.annotation.conditioncontext; import org.springframework.core.type.annotatedtypemetadata; public class windowscondition implements condition { @override public boolean matches(conditioncontext conditioncontext, annotatedtypemetadata annotatedtypemetadata) { return conditioncontext.getenvironment().getproperty("os.name").contains("windows"); } }
package chapter03.conditional; import org.springframework.context.annotation.condition; import org.springframework.context.annotation.conditioncontext; import org.springframework.core.type.annotatedtypemetadata; public class linuxcondition implements condition { @override public boolean matches(conditioncontext conditioncontext, annotatedtypemetadata annotatedtypemetadata) { return conditioncontext.getenvironment().getproperty("os.name").contains("linux"); } }
值得注意的是,这2个类都需要实现condition接口,并重写方法matches(),如果该方法返回true时,使用该条件的1个或多个bean就会被装配,如果该方法返回false,使用该条件的1个或多个bean就会被忽略。
然后,定义java配置类conditionalconfig:
package chapter03.conditional; import org.springframework.context.annotation.bean; import org.springframework.context.annotation.conditional; import org.springframework.context.annotation.configuration; @configuration public class conditionalconfig { @bean @conditional(windowscondition.class) public listservice windowslistservice() { return new windowslistservice(); } @bean @conditional(linuxcondition.class) public listservice linuxlistservice() { return new linuxlistservice(); } }
这里声明bean时除了使用@bean注解,还使用了@conditional注解,这个注解是实现条件化的bean的关键,它的参数可以传递任何实现了condition接口并重写了matches()方法的类,这里传递的是我们上面定义的windowscondition和linuxcondition。
最后,我们定义一个main类,在其main()方法中添加如下测试代码:
package chapter03.conditional; import org.springframework.context.annotation.annotationconfigapplicationcontext; public class main { public static void main(string[] args) { annotationconfigapplicationcontext context = new annotationconfigapplicationcontext(conditionalconfig.class); listservice listservice = context.getbean(listservice.class); system.out.println(context.getenvironment().getproperty("os.name") + "系统下的列表命令为:" + listservice.showlistcmd()); context.close(); } }
运行结果如下所示:
this is windowslistservice constructor
windows 7系统下的列表命令为:dir
从运行日志可以看出,由于当前系统是windows 7,我们声明的linuxlistservice bean并没有被装配。
3. 源码及参考
源码地址:,欢迎下载。
汪云飞《java ee开发的颠覆者:spring boot实战》
craig walls 《spring实战(第4版)》
4. 最后
打个小广告,欢迎扫码关注微信公众号:「申城异乡人」,定期分享java技术干货,让我们一起进步。
推荐阅读
-
序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询 多表关联查询
-
spring源码分析系列5:ApplicationContext的初始化与Bean生命周期
-
02Spring基于xml的IOC配置--实例化Bean的三种方式
-
Spring高级装配,Profile的使用,条件化Bean,解决歧义性
-
spring初始化bean时执行某些方法完成特定的初始化操作
-
Spring5 - Bean的初始化和销毁的4种方式
-
Spring源码解析六 (Bean的初始化)
-
Spring Bean的实例化之属性注入源码剖析过程
-
spring源码深度解析— IOC 之 bean 的初始化
-
Spring入门 IOC理论,第一个spring程序Di依赖注入,Bean的自动装配