Spring Boot条件化自动装配
2023-06-13 09:12:41 时间
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();
}
}
相关文章
- 关于spring boot自动注入出现Consider defining a bean of type ‘xxx‘ in your configuration问题解决方案
- Spring 全家桶之 Spring Boot 2.6.4(五)- WebMvcAutoConfiguration(Part D)
- 横跨Java后端关键技术,Spring Boot终极体系做到了
- Spring框架:第三章:对象的生命周期及单例bean生命周期的11个步骤
- spring boot整合shiro_Spring框架介绍及使用
- Spring boot 启动错误:Could not resolve placeholder
- Spring Boot + Netty + WebSocket 实现消息推送
- Spring-boot_Spring Boot
- Spring Boot + Elasticsearch实现大批量数据集下中文的精确匹配-案例剖析
- spring boot 启动的时候required a bean of type 'XXX' that could not be
- SpringBoot:模块探究之spring-boot-starters
- 使用spring-boot-starter-data-elasticsearch 设置了long,为什么却变成了keyword类型
- Spring:声明式事务
- Spring Boot | 集成MapStruct实现不同类型Java对象间的自动转换
- Spring Boot 如何集成JWT实现Token验证
- Spring Boot的核心注解和配置(一)
- Spring Boot的事务管理(一)
- Spring Cloud Task重启任务
- Spring Boot 2.0 多图片上传加回显
- Spring MVC拦截器(Interceptor)
- spring boot 自动部署方案详解架构师
- spring mvc返回json字符串的方式详解编程语言
- Spring Cloud(十二):Spring Cloud Zuul 限流详解(附源码)编程语言
- Spring Cloud(二):Spring Cloud Eureka Server高可用注册服务中心的配置详解编程语言
- Spring Boot(二十):使用spring-boot-admin对spring-boot服务进行监控详解编程语言
- spring Boot(十九):使用Spring Boot Actuator监控应用详解编程语言
- Spring Boot(一):入门篇详解编程语言
- spring boot 接口返回值去掉为null的字段详解编程语言