共计 5926 个字符,预计需要花费 15 分钟才能阅读完成。
1、Class 条件注解
Class 条件注解有一对语义相反的注解,@ConditionalOnClass 和 @ConditionalOnMissClass 分别表达 ” 当指定类存在时 ” 和 ” 当指定类不存在时 ” 的语义。
源码:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {/**
* The classes that must be present. Since this annotation is parsed by loading class
* bytecode, it is safe to specify classes here that may ultimately not be on the
* classpath, only if this annotation is directly on the affected component and
* <b>not</b> if this annotation is used as a composed, meta-annotation. In order to
* use this annotation as a meta-annotation, only use the {@link #name} attribute.
* @return the classes that must be present
*/
Class<?>[] value() default {};
/**
* The classes names that must be present.
* @return the class names that must be present.
*/
String[] name() default {};}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnMissingClass {/**
* The names of the classes that must not be present.
* @return the names of the classes that must not be present
*/
String[] value() default {};}
2、案例:
如果工程中有 Jackson 时, 使用 JSON 序列化, 没有使用 String.valueOf()格式化
2.1、增加 Jackson 依赖到 pom.xml, 保持 为 true
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
<optional>true</optional>
</dependency>
2.2、新增 JSON Formatter 实现
public class JsonFormatter implements Formatter {private final ObjectMapper objectMapper;
public JsonFormatter(){this.objectMapper=new ObjectMapper();}
// 将对对象转换为 json 字符串
public String format(Object obj) {try{return objectMapper.writeValueAsString(obj);
}catch (JsonProcessingException e){throw new IllegalArgumentException(e);
}
}
}
2.3、新增 JsonFormatter Bean 声明到 FormatterAutoConfiguration
@Configuration
public class FormatterAutoConfiguration {@Bean
@ConditionalOnMissingClass(value = "com.fasterxml.jackson.databind.ObjectMapper")// 如果 classpath 下没有 ObjectMapper 时
public Formatter defaultFormatter(){return new DefaultFormatter();}
@Bean
@ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")// 如果 classpath 下有 ObjectMapper 时
public Formatter jsonFormatter(){return new JsonFormatter();}
}
2.4、重新构建 formatter-spring-boot-starter
mvn -Dmaven.test.skip -U clean install
2.5、加入 formatter-spring-boot-starter
<dependency>
<groupId>com.tyschool</groupId>
<artifactId>formatter-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
3、Bean 条件注解
Bean 条件注解也是成对出现的, 例如 @ConditionalOnBean 和 @ConditionalOnMissBean。ConditionOnBean 仅匹配应用上下文中已处理的 BeanDefinition。ConditionalOnMissBean 逻辑相反。
源码:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {Class<?>[] value() default {};
String[] type() default {};
Class<? extends Annotation>[] annotation() default {};
String[] name() default {};
SearchStrategy search() default SearchStrategy.ALL;
Class<?>[] parameterizedContainer() default {};}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnMissingBean {Class<?>[] value() default {};
String[] type() default {};
Class<?>[] ignored() default {};
String[] ignoredType() default {};
Class<? extends Annotation>[] annotation() default {};
String[] name() default {};
SearchStrategy search() default SearchStrategy.ALL;
Class<?>[] parameterizedContainer() default {};}
4、Json 格式化案例
-
当前 ObjectMapper Class 不存在时,Bean 为 DefaultFormatter 实例, 其名称为 ”defaultFormatter”
-
当前 ObjectMapper Class 不存在时且具有 Bean 不存在时,BeanJsonFormatter 默认构造器创建 ObjectMapper 实例, 其名称为 ”jsonFormatter”
-
当 ObjectMapper Class 存在且其 Bean 也存在时,Bean 为 JsonFormatter 构造器注入 ObjectMapperBean, 其名称为 ”objectMapperFormatter”
提示:
ObjectMapper Bean 的初始化需要满足以下条件:
-
ObjectMapper 必须存在于 Class Path 中
-
Jackson2ObjectMapperBuilder 必须在 Class Path 中, 源于 org.springframework:spring-web 4.1.1, 工程需依赖 spring-boot-strater-web 1.2.0 及以上版本
-
ObjectMapper Bean 必须在所有 Spring 应用上下文中
4.1、增加 Jackson2ObjectMapperBuilder Maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.6.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
<optional>true</optional>
</dependency>
</dependencies>
4.2、增加 JsonFormatter 构造器
private final ObjectMapper objectMapper;
public JsonFormatter(){this(new ObjectMapper());
}
public JsonFormatter(ObjectMapper objectMapper){this.objectMapper=objectMapper;
}
4.3、新增 JsonFormatterBean
@Configuration
public class FormatterAutoConfiguration {@Bean
@ConditionalOnMissingClass(value = "com.fasterxml.jackson.databind.ObjectMapper")// 如果 classpath 下没有 ObjectMapper 时
public Formatter defaultFormatter(){return new DefaultFormatter();}
@Bean
@ConditionalOnClass(name = "com.fasterxml.jackson.databind.ObjectMapper")// 如果 classpath 下有 ObjectMapper 时
@ConditionalOnMissingBean(Servlet.class)
public Formatter jsonFormatter(){return new JsonFormatter();}
@Bean
@ConditionalOnBean(Servlet.class)// 如果 classpath 有 Servlet 时
public Formatter objectMapperFormatter(ObjectMapper objectMapper){return new JsonFormatter(objectMapper);
}
}
4.4、重新构建 formatter-spring-boot-starter
mvn -Dmaven.test.skip -U clean install
4.5、引入 formatter-spring-boot-starter
<dependency>
<groupId>com.tyschool</groupId>
<artifactId>formatter-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
4.6、重构引导类
@SpringBootApplication
public class FormatterBootStrap {public static void main(String[] args) {// 创建 Spring 上下文
ConfigurableApplicationContext context = new SpringApplicationBuilder(FormatterBootStrap.class)
.web(WebApplicationType.SERVLET)
.run(args);
final Map<String, Object> map = new HashMap<String, Object>();
map.put("name","tyschool");
// 获取 bean
Map<String, Formatter> beans = context.getBeansOfType(Formatter.class);
// 格式化数据
beans.forEach((beanName,formatter)->{System.out.println(beanName+""+formatter.getClass().getSimpleName()+" "+formatter.format(map));
});
context.close();}
}