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