本章将介绍 @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 地址,运行效果如下图: