Spring自动配置之condition条件判断上篇
作者:lxrqiyuan
前言
Condition是在Spring4.0增加的条件判断功能,通过这个功能可以实现选择性的创建Bean对象。
引入一个例子
SpringBoot是如何知道要创建哪个Bean的?比如SpringBoot是如何知道要创建RedisTemplate的?
在SpringBoot中获取应用上下文对象context,通过其getBean方法获取Bean对象
package cs.yangtze.springboot_condition; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class SpringbootConditionApplication { public static void main(String[] args) { //启动springboot的应用,返回spring的IOC容器 ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args); //获取bean,redisTemplate Object redisTemplate = context.getBean("redisTemplate"); System.out.println(redisTemplate); } }
启动项目之后会报一个这样的错误:No Such Bean,这是因为我们还没有导入redis的起步依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
导入依赖后,这时SpringBoot就能够识别这样的bean对象了
通过这个例子,我们来想一想,为什么我们没有导入redis依赖的时候,SpringBoot不会为我们创建这个redisTemplate的bean对象?
SpringBoot做的事情就是判断当前环境中有没有一个redis对应的所需要的字节码文件,有的话就会帮你创建被俺对象,没有就不会创建。这时候我们就会用condition来实现。
condition的一个案例
需求:在Spring的IOC容器中有一个USer的Bean,现要求:导入Jedis坐标后加载该Bean,没导入,则不加载。
首先创建一个实体类User,不需要成员变量
然后创建condition的实现类ClassCondition,它只有一个需要重写的方法matches,返回值类型为布尔类型,至于这个返回值有什么作用,下面会有解释。
在这个重写的方法中我们就要去实现需求:导入Jedis坐标后加载该Bean。其中是一个很简单的逻辑,如果我们导入了Jedis的依赖,那我们就可以通过Class.forName(“redis.clients.jedis.Jedis”)来获取与给定的字符串名称相关联类或接口的Class对象,如果能够获取到就返回true,否则返回false。
package cs.yangtze.springboot_condition.condition; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; public class ClassCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { //需求:导入jedis坐标后创建Bean boolean flag = true; try { Class<?> aClass = Class.forName("redis.clients.jedis.Jedis"); } catch (ClassNotFoundException e) { flag = false; } return flag; } }
然后创建一个配置类UserConfig,用来创建User的Bean对象
注意:在方法的上面还有一个Conditional的注解,这就是今天的重点!!!
Conditional括号中的参数是一个或多个condition的实现类,这时候就会用到上面提到的返回值,若重写的match方法返回的是TRUE,则条件成立(即我导入了Jedis坐标),那么IOC容器就会帮我去创建bean对象,否则不会。
package cs.yangtze.springboot_condition.config; import cs.yangtze.springboot_condition.condition.ClassCondition; import cs.yangtze.springboot_condition.entity.User; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration public class UserConfig { @Bean//用于在容器中闯进Bean对象 @Conditional(ClassCondition.class) //参数是一个或多个condition的实现类 public User user(){ return new User(); } }
最后在启动类中通过上下文对象来获取该bean对象
package cs.yangtze.springboot_condition; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class SpringbootConditionApplication { public static void main(String[] args) { //启动springboot的应用,返回spring的IOC容器 ConfigurableApplicationContext context = SpringApplication.run(SpringbootConditionApplication.class, args); //获取bean,redisTemplate Object redisTemplate = context.getBean("redisTemplate"); System.out.println(redisTemplate); //此处getBean方法中的参数是UserConfig类中的方法名称,当然也可以在@Bean注解后加入名称,如@Bean("aaa"),那么此处的user就应换成aaa Object user = context.getBean("user"); System.out.println(user); } }
结果演示:当我导入Jedis坐标时,能够正常获取对象
未导入时
补充:Jedis坐标
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency>
总结
本文中的是否jedis坐标只是一个简单的例子,当然也可以换成其他的条件,目的就是为了展示condition的功能,就是通过判断来选择性的创建bean对象。
到此这篇关于Spring自动配置之condition条件判断上篇的文章就介绍到这了,更多相关Spring condition条件判断内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!