Spring Boot 教程

@ConditionalOnJava 注解

本章将介绍 @ConditionalOnJava 注解的用法,该注解将根据应用程序正在运行的 JVM 版本进行匹配 @Conditional 注解。

在开始使用 @ConditionalOnJava 注解之前,我们先看看它的源码,如下:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnJavaCondition.class)
public @interface ConditionalOnJava {
   /**
    * 指定在 value() 中配置的值应该怎样去匹配边界。
    * 默认为 Range.EQUAL_OR_NEWER,即大于等于
    */
   Range range() default Range.EQUAL_OR_NEWER;

   /**
    * JavaVersion 进行检查。使用 range() 来指定配置的值是上限还是下限
    */
   JavaVersion value();

   /**
    * Range 可选项
    */
   enum Range {
      // 等于或大于指定的 JavaVersion
      EQUAL_OR_NEWER,
      // 小于指定的 JavaVersion
      OLDER_THAN
   }
}

继续分析一下 OnJavaCondition 类的 getMatchOutcome() 方法的源码,如下:

@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
    // 获取 @ConditionalOnJava 注解的属性和属性值
    Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnJava.class.getName());
    // 获取 range 属性的值
    Range range = (Range) attributes.get("range");
    // 获取 value 属性的值
    JavaVersion version = (JavaVersion) attributes.get("value");
    // 与当前运行的 JVM 版本进行比较
    return getMatchOutcome(range, JVM_VERSION, version);
}

protected ConditionOutcome getMatchOutcome(Range range, JavaVersion runningVersion, JavaVersion version) {
    // 版本比较
    boolean match = isWithin(runningVersion, range, version);
    // 构建提示信息
    String expected = String.format((range != Range.EQUAL_OR_NEWER) ? "(older than %s)" : "(%s or newer)", version);
    ConditionMessage message = ConditionMessage.forCondition(ConditionalOnJava.class, expected)
            .foundExactly(runningVersion);
    return new ConditionOutcome(match, message);
}

private boolean isWithin(JavaVersion runningVersion, Range range, JavaVersion version) {
    // 判断运行的JVM版本是否大于等于指定版本
    if (range == Range.EQUAL_OR_NEWER) {
        return runningVersion.isEqualOrNewerThan(version);
    }
    // 判断运行的JVM版本是否小于指定版本
    if (range == Range.OLDER_THAN) {
        return runningVersion.isOlderThan(version);
    }
    throw new IllegalStateException("Unknown range " + range);
}

示例

(1)创建两个服务,分别为 UserService(用户服务) 和 OrderService(订单服务),如下:

a、UserService.java

package com.huangx.springboot.autoconfig.service;

public class UserService {
    // 什么也不做
}

b、OrderService.java

package com.huangx.springboot.autoconfig.service;

public class OrderService {
    // 什么也不做
}

(2)创建用户和订单 @Configuration 配置类,如下:

a、UserConfig.java

package com.huangx.springboot.autoconfig.config;

import com.huangx.springboot.autoconfig.service.UserService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava;
import org.springframework.boot.system.JavaVersion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
// 要求 JDK 必须大于等于 1.8
// 注意:默认 range 为 Range.EQUAL_OR_NEWER,即大于等于
@ConditionalOnJava(JavaVersion.EIGHT)
public class UserConfig {

    @Bean
    public UserService userService() {
        System.out.println("UserService -> userService()");
        return new UserService();
    }

}

b、OrderConfig.java

package com.huangx.springboot.autoconfig.config;

import com.huangx.springboot.autoconfig.service.OrderService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnJava;
import org.springframework.boot.system.JavaVersion;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
// 要求 JDK 必须大于等于 JDK9
// 注意:默认 range 为 Range.EQUAL_OR_NEWER,即大于等于
@ConditionalOnJava(value = JavaVersion.NINE,
        range = ConditionalOnJava.Range.EQUAL_OR_NEWER)
public class OrderConfig {

    @Bean
    public OrderService orderService() {
        System.out.println("OrderConfig -> orderService()");
        return new OrderService();
    }

}

(3)客户端代码,验证用户和订单服务是否被实例化。如下:

package com.huangx.springboot.autoconfig;

import com.huangx.springboot.autoconfig.service.OrderService;
import com.huangx.springboot.autoconfig.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class Demo5Application {

    @Autowired
    private ApplicationContext applicationContext;

    public static void main(String[] args) {
        SpringApplication.run(Demo5Application.class, args);
    }

    @GetMapping("/")
    public String index() {
        UserService userService = null;
        try {
            userService = applicationContext.getBean(UserService.class);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        OrderService orderService = null;
        try {
            orderService = applicationContext.getBean(OrderService.class);
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }

        return "userService=" + userService + "<br/>" +
                "orderService=" + orderService;
    }

}

启动 Spring Boot 程序,然后在浏览器中访问 http://localhost:8080 地址,运行效果如下图:

说说我的看法
全部评论(
没有评论
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号