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 {};
}
如果工程中有Jackson时,使用JSON序列化,没有使用String.valueOf()格式化
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.3</version>
<optional>true</optional>
</dependency>
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);
}
}
}
@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();
}
}
mvn -Dmaven.test.skip -U clean install
<dependency>
<groupId>com.tyschool</groupId>
<artifactId>formatter-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
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 {};
}
提示:
ObjectMapper Bean的初始化需要满足以下条件:
<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>
private final ObjectMapper objectMapper;
public JsonFormatter(){
this(new ObjectMapper());
}
public JsonFormatter(ObjectMapper objectMapper){
this.objectMapper=objectMapper;
}
@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);
}
}
mvn -Dmaven.test.skip -U clean install
<dependency>
<groupId>com.tyschool</groupId>
<artifactId>formatter-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
@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();
}
}