阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Spring Boot条件化自动装配

168次阅读
没有评论

共计 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();} }

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-06-06发表,共计5926字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中