SpringBoot的入门(二)

简介: SpringBoot的入门(二)

SpringBoot-按照条件去装配对象

先给出例子:根据配置项的编码格式来配置不同的编码转换器:

1,创建一个编码格式转换器接口

  1. package com.boot.condition.bootconditionconfig.converter;

  2. /**
  3. * 编码格式的转换接口
  4. */
  5. public interface EncodingConverter {

  6. }

2,创建两个转换器的实现类UTF8,和GBK的:

  1. package com.boot.condition.bootconditionconfig.converter;

  2. public class GBKEncodingConverter implements  EncodingConverter {


  3. }
  4. package com.boot.condition.bootconditionconfig.converter;

  5. public class UTF8EncodingConverter implements  EncodingConverter {

  6. }

3,把上面的两个转换器的实现类通过配置类的方式来装载到spring容器中去:在装配EncodingConverterConfig这个对象的同时把Bean对象的实例装配进去。

  1. package com.boot.condition.bootconditionconfig.config;
  2. import com.boot.condition.bootconditionconfig.condition.GBKCondition;
  3. import com.boot.condition.bootconditionconfig.converter.EncodingConverter;
  4. import com.boot.condition.bootconditionconfig.converter.GBKEncodingConverter;
  5. import com.boot.condition.bootconditionconfig.converter.UTF8EncodingConverter;
  6. import org.springframework.boot.SpringBootConfiguration;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Conditional;
  9. @SpringBootConfiguration
  10. public class EncodingConverterConfig {
  11.    @Bean

  1.    public EncodingConverter createGbkEncodingConverter(){
  2.        return new GBKEncodingConverter();
  3.    }
  4.    @Bean
  5.    public EncodingConverter createUtf8EncodingConverter(){
  6.        return new UTF8EncodingConverter();
  7.    }
  8. }

4,在主函数里面拿出接口下面的所有的在spring容器中的实例:

  1. package com.boot.condition.bootconditionconfig;
  2. import com.boot.condition.bootconditionconfig.converter.EncodingConverter;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.context.ConfigurableApplicationContext;

  6. import java.util.Map;

  7. @SpringBootApplication
  8. public class BootConditionConfigApplication {
  9.    public static void main(String[] args) {
  10.        ConfigurableApplicationContext context =
  11.                SpringApplication.run(BootConditionConfigApplication.class, args);
  12.        Map<String, EncodingConverter> beansOfType = context.getBeansOfType(EncodingConverter.class);
  13.        System.out.println(beansOfType);
  14.        context.close();
  15.    }

  16. }

运行的结果如下:这时就把两个bean的实例装配到spring容器中了。

提问:在一次的运行当中不可能用到两个转换器的过程,比如:我想要GBK的就用GBK的转换器来转换,如果想用UTF-8的就用UTF-8的转换器来转换。

按照上面的做法是做不到的,如何去通过配置去装配要装配的对象呢?

这时需要用@Conditional的注解和Condition的接口:

来看下@Conditional的注解:

这个注解就是一个普通的注解:就是一个条件:里面有一个Class类型的

value的属性,要求的范围必须是Condition的子接口,实现或者继承这个接口的子类。才能够成为Conditioanl注解对应的操作类:

  1. package org.springframework.context.annotation;

  2. import java.lang.annotation.Documented;
  3. import java.lang.annotation.ElementType;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;

  7. @Target({ElementType.TYPE, ElementType.METHOD})
  8. @Retention(RetentionPolicy.RUNTIME)
  9. @Documented
  10. public @interface Conditional {
  11.    Class<? extends Condition>[] value();


实际上Condition是一个接口:里面有一个抽象方法的声明。一个参数是ConditionContext类型的参数,一个是AnnotatedTypeMetadata:获取注解上的元数据的信息。里面的方法:matches,当方法的返回值为true的时候就会把bean对象装配到spring容器中去。当返回false的时候就不会装配进去。

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //

  5. package org.springframework.context.annotation;

  6. import org.springframework.core.type.AnnotatedTypeMetadata;

  7. @FunctionalInterface
  8. public interface Condition {
  9.    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
  10. }

我们可以在ConditionContext里面可以拿很多的东西:1,可以拿到当前注册的bean对象。2,工厂对象。3,环境。4,资源装载器。5,类加载器。

  1. package org.springframework.context.annotation;

  2. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
  3. import org.springframework.beans.factory.support.BeanDefinitionRegistry;
  4. import org.springframework.core.env.Environment;
  5. import org.springframework.core.io.ResourceLoader;
  6. import org.springframework.lang.Nullable;

  7. public interface ConditionContext {
  8.    BeanDefinitionRegistry getRegistry();

  9.    @Nullable
  10.    ConfigurableListableBeanFactory getBeanFactory();

  11.    Environment getEnvironment();

  12.    ResourceLoader getResourceLoader();

  13.    @Nullable
  14.    ClassLoader getClassLoader();
  15. }

在AnnotatedTypeMetadata里面可以获取到:就是获取类上面注解所对应的信息都可以拿出来,这块的信息可以在@Enable*的工作原理会写到

  1. package org.springframework.core.type;

  2. import java.util.Map;
  3. import org.springframework.lang.Nullable;
  4. import org.springframework.util.MultiValueMap;

  5. public interface AnnotatedTypeMetadata {
  6.    boolean isAnnotated(String var1);

  7.    @Nullable
  8.    Map<String, Object> getAnnotationAttributes(String var1);

  9.    @Nullable
  10.    Map<String, Object> getAnnotationAttributes(String var1, boolean var2);

  11.    @Nullable
  12.    MultiValueMap<String, Object> getAllAnnotationAttributes(String var1);

  13.    @Nullable
  14.    MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);
  15. }

5:解决办法如何按照条件的方式去装配我们的对象呢?可以通过运行时的参数来更改file.encoding的编码格式从而选择不同的编码格式的转换器:在运行的过程中通过下面的方式去适配。

  1. package com.boot.condition.bootconditionconfig.condition;
  2. import org.springframework.context.annotation.Condition;
  3. import org.springframework.context.annotation.ConditionContext;
  4. import org.springframework.core.type.AnnotatedTypeMetadata;
  5. public class GBKCondition implements Condition {
  6.    @Override
  7.    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
  8.        String encoding = System.getProperty("file.encoding");
  9.        if("gbk".equals(encoding.toLowerCase())){
  10.            return true;
  11.        }
  12.        return false;
  13.    }
  14. }
  15. package com.boot.condition.bootconditionconfig.condition;

  16. import org.springframework.context.annotation.Condition;
  17. import org.springframework.context.annotation.ConditionContext;
  18. import org.springframework.core.type.AnnotatedTypeMetadata;

  19. public class UTF8Condition implements Condition {
  20.    @Override
  21.    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
  22.        String encoding = System.getProperty("file.encoding");
  23.        if("utf-8".equals(encoding.toLowerCase())){
  24.            return true;
  25.        }
  26.        return false;
  27.    }
  28. }

在装配对象的时候需要加上@Conditional的注解:这样就可以按照条件装配我们的对象:当装配下面的对象的时候会回调condition接口中的方法。

  1. package com.boot.condition.bootconditionconfig.config;
  2. import com.boot.condition.bootconditionconfig.condition.GBKCondition;
  3. import com.boot.condition.bootconditionconfig.condition.UTF8Condition;
  4. import com.boot.condition.bootconditionconfig.converter.EncodingConverter;
  5. import com.boot.condition.bootconditionconfig.converter.GBKEncodingConverter;
  6. import com.boot.condition.bootconditionconfig.converter.UTF8EncodingConverter;
  7. import org.springframework.boot.SpringBootConfiguration;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Conditional;
  10. @SpringBootConfiguration
  11. public class EncodingConverterConfig {
  12.    @Bean
  13.    @Conditional(GBKCondition.class)
  14.    public EncodingConverter createGbkEncodingConverter(){
  15.        return new GBKEncodingConverter();
  16.    }
  17.    @Bean
  18.    @Conditional(UTF8Condition.class)
  19.    public EncodingConverter createUtf8EncodingConverter(){
  20.        return new UTF8EncodingConverter();
  21.    }
  22. }

改变下运行时的参数如下:

运行的结果如下:如果把运行时的参数改为utf-8的就只会装配utf-8的转换器。

这个@Conditonal的注解可以用到方法的上面,也可以用到类上面。

代码如下:

  1. package com.boot.condition.bootconditionconfig.config;
  2. import com.boot.condition.bootconditionconfig.condition.GBKCondition;
  3. import com.boot.condition.bootconditionconfig.condition.UTF8Condition;
  4. import com.boot.condition.bootconditionconfig.converter.EncodingConverter;
  5. import com.boot.condition.bootconditionconfig.converter.GBKEncodingConverter;
  6. import com.boot.condition.bootconditionconfig.converter.UTF8EncodingConverter;
  7. import org.springframework.boot.SpringBootConfiguration;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Conditional;
  10. @SpringBootConfiguration
  11. @Conditional(GBKCondition.class)
  12. public class EncodingConverterConfig {
  13.    @Bean
  14.    public EncodingConverter createGbkEncodingConverter(){
  15.        return new GBKEncodingConverter();
  16.    }
  17.    @Bean
  18.    public EncodingConverter createUtf8EncodingConverter(){
  19.        return new UTF8EncodingConverter();
  20.    }
  21. }

运行结果如下:这时两个对象都会装配进去。这个注解标在类上了,如果返回的结果为flase的话,相当于一个对象都不会装配进去,如果为true的话,这两个对象都会装配进去。

@Conditional的注解里面可以配置多个,是与的关系,如果同时为true的话,才会装配进去:代码如下:

  1. package com.boot.condition.bootconditionconfig.config;
  2. import com.boot.condition.bootconditionconfig.condition.GBKCondition;
  3. import com.boot.condition.bootconditionconfig.condition.UTF8Condition;
  4. import com.boot.condition.bootconditionconfig.converter.EncodingConverter;
  5. import com.boot.condition.bootconditionconfig.converter.GBKEncodingConverter;
  6. import com.boot.condition.bootconditionconfig.converter.UTF8EncodingConverter;
  7. import org.springframework.boot.SpringBootConfiguration;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.context.annotation.Conditional;
  10. @SpringBootConfiguration
  11. @Conditional({GBKCondition.class,UTF8Condition.class})
  12. public class EncodingConverterConfig {
  13.    @Bean
  14.    public EncodingConverter createGbkEncodingConverter(){
  15.        return new GBKEncodingConverter();
  16.    }
  17.    @Bean
  18.    public EncodingConverter createUtf8EncodingConverter(){
  19.        return new UTF8EncodingConverter();
  20.    }
  21. }

运行的结果如下:

总结:使用按照条件装配的过程:

  1. @Conditional  [value的值必须事实现Condition接口的类]
  2. 根据接口中的matches方法的返回值确定事否装配bean对象到spring容器中:false不装配,true就会装配到spring容器中去。

在springBoot里面提供这样的注解很多:比如@ConditionalOnClass:(如果在classpath下存在这个文件的话,这个时候也会被装载)

@ConditionalOnBean:(只要在spring容器中存在了这个bea类的话就被装载到spring容器中去)等等

相关文章
|
2月前
|
JSON Java API
SpringBoot入门(八)
SpringBoot入门(八)
|
2月前
|
NoSQL Java Redis
SpringBoot的入门(一)
SpringBoot的入门(一)
|
2月前
|
Java 容器 Spring
SpringBoot入门(六)
SpringBoot入门(六)
|
2月前
|
消息中间件 NoSQL Java
SpringBoot的入门(五)
SpringBoot的入门(五)
|
2月前
|
Java API 容器
SpringBoot入门(十)
SpringBoot入门(十)
|
2月前
|
Java Spring 容器
SpringBoot的入门(三)
SpringBoot的入门(三)
|
2月前
|
监控 Java Spring
SpringBoot的入门(四)
SpringBoot的入门(四)
|
2月前
|
Java 应用服务中间件 nginx
SpringBoot入门(九)
SpringBoot入门(九)
|
2月前
|
JSON Java 数据格式
SpringBoot入门(七)
SpringBoot入门(七)
|
5月前
|
Java 数据库连接 Maven