SpringBoot中condition注解的使用

在项目中,有时会遇到我们的Configuration、Bean、Service等等的bean组件需要依条件按需加载的情况。
springboot中提供了一系列@Condition* 注解来处理有条件注入的情况。

1. 说明

Spring4中增加了@Condition annotation, 使用该Annotation之后,在做依赖注入的时候,会检测是否满足某个条件来决定是否注入某个类。
springboot基于spring4的这个注解实现了多个用于判断的条件注解,如果我们在使用中这些注解无法满足我们的要求还可以使用@Conditional自定义条件注解

2. 常用的条件注解

条件注解对应的Condition 处理类处理逻辑
@ConditionalOnBeanOnBeanConditionSpring容器中是否存在对应的实例。可以通过实例的类型、类名、注解、昵称去容器中查找(可以配置从当前容器中查找或者父容器中查找或者两者一起查找)
@ConditionalOnClassOnClassCondition类加载器中是否存在对应的类。可以通过Class指定(value属性)或者Class的全名指定(name属性)如果是多个类或者多个类名的话,关系是”与”关系,也就是说这些类或者类名都必须同时在类加载器中存在
@ConditionalOnExpressionOnExpressionCondition判断SpEL 表达式是否成立
@ConditionalOnMissingBeanOnBeanConditionSpring容器中是否缺少对应的实例。可以通过实例的类型、类名、注解、昵称去容器中查找(可以配置从当前容器中查找或者父容器中查找或者两者一起查找)
@ConditionalOnMissingClassOnClassCondition跟ConditionalOnClass的处理逻辑一样,只是条件相反,在类加载器中不存在对应的类
@ConditionalOnPropertyOnPropertyCondition应用环境中的屬性是否存在。提供prefix、name、havingValue以及matchIfMissing属性。prefix表示属性名的前缀,name是属性名,havingValue是具体的属性值,matchIfMissing是个boolean值,如果属性不存在,这个matchIfMissing为true的话,会继续验证下去,否则属性不存在的话直接就相当于匹配不成功
@ConditionalOnResourceOnResourceCondition是否存在指定的资源文件。只有一个属性resources,是个String数组。会从类加载器中去查询对应的资源文件是否存在
@ConditionalOnSingleCandidateOnBeanConditionSpring容器中是否存在且只存在一个对应的实例。只有3个属性value、type、search。跟ConditionalOnBean中的这3种属性值意义一样
@ConditionalOnWebApplicationOnWebApplicationCondition应用程序是否是Web程序,没有提供属性,只是一个标识。会从判断Web程序特有的类是否存在,环境是否是Servlet环境,容器是否是Web容器等
举例
例子说明
@ConditionalOnBean(javax.sql.DataSource.class)Spring容器或者所有父容器中需要存在至少一个javax.sql.DataSource类的实例
@ConditionalOnClass({ Configuration.class,FreeMarkerConfigurationFactory.class })类加载器中必须存在Configuration和FreeMarkerConfigurationFactory这两个类
@ConditionalOnExpression(“’${server.host}’==’localhost’”)server.host配置项的值需要是localhost
ConditionalOnJava(JavaVersion.EIGHT)Java版本至少是8
@ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)Spring当前容器中不存在ErrorController类型的bean
@ConditionalOnMissingClass(“GenericObjectPool”)类加载器中不能存在GenericObjectPool这个类
@ConditionalOnNotWebApplication必须在非Web应用下才会生效
@ConditionalOnProperty(prefix = “spring.aop”, name = “auto”, havingValue = “true”, matchIfMissing = true)应用程序的环境中必须有spring.aop.auto这项配置,且它的值是true或者环境中不存在spring.aop.auto配置(matchIfMissing为true)
@ConditionalOnResource(resources=”mybatis.xml”)类加载路径中必须存在mybatis.xml文件
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)Spring当前或父容器中必须存在PlatformTransactionManager这个类型的实例,且只有一个实例
@ConditionalOnWebApplication必须在Web应用下才会生效

3.自定义条件注解

实现条件化注解我们需要两个类

  • 自定义注解类
    定义注解,指定判断用的条件类
  • 条件类
    实现org.springframework.context.annotation.Condition接口,定义判断条件

举例说明:
1.定义注解类MyConditionalOnProperty
要使用注解@Conditional(MyOnPropertyCondition.class),MyOnPropertyCondition为我们要定义的条件类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional(MyOnPropertyCondition.class)
public @interface MyConditionalOnProperty {
    String value();
    String prefix() default "";
    String havingValue() default "";
    boolean matchIfMissing() default false;
    boolean relaxedNames() default true;
    //TODO ADD ONE PROPERTY
    String havingValue() default "";
}

2.定义条件类:

public class MyOnPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(MyConditionalOnProperty.class.getName());
        String propertyName = (String) annotationAttributes.get("value");
        String value = annotationAttributes.get("havingValue");
        String propertyValue = context.getEnvironment().getProperty(propertyName);
       
        if (propertyValue.equalsIgnoreCase(value)) {
            return true;
        }
        return false;
    }
}

3.调用

   @Configuration
    public class MyConfig {
        @Bean
        @MyConditionalOnProperty(value = "env",havingValue = "dev")
        public Person person(){
            log.info("创建Bean");
            return new Person();
        }
    }
@Cacheable注解是Spring框架用于缓存方法返回结果的注解。当一个方法被@Cacheable注解标记后,Spring会检查缓存是否存在该方法的返回值,如果存在,则直接从缓存获取结果并返回;如果不存在,则执行方法体,并将返回值存入缓存使用@Cacheable注解需要注意以下几点: 1. 在需要缓存结果的方法上使用@Cacheable注解。 2. 可以指定缓存的名称,通过value属性来指定,如:@Cacheable(value="myCache")。 3. 可以指定缓存的Key,通过key属性来指定,如:@Cacheable(key="#param")。其#param表示方法的参数值,还可以使用SpEL表达式来动态构建key。 4. 默认情况下,缓存的Key是由方法的所有参数组成的,如果不希望使用所有参数构建Key,可以使用condition属性来限制条件,如:@Cacheable(condition="#param.length() < 10")。这里的condition表示只有当参数长度小于10时才进行缓存。 5. 可以指定缓存的过期时间,通过设置expire属性来指定,如:@Cacheable(expire=3600)。单位为秒,默认为-1,表示永不过期。 示例代码: ```java @Service public class UserService { @Cacheable(value = "users", key = "#id") public User getUserById(String id) { // 从数据库获取用户信息 // ... return user; } } ``` 上述示例,getUserById方法会根据id参数从缓存获取User对象,如果缓存不存在,则执行方法体并将返回值存入缓存。 需要注意的是,@Cacheable注解只能用于Spring容器管理的Bean,即被@Service、@Component等注解标记的类的方法才能被缓存。另外,为了使@Cacheable注解生效,需要在Spring配置文件配置缓存管理器(如使用Ehcache、Redis等)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刀不封

打赏就是对作者的一种赞赏和鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值