• (007)Spring Boot之自动装配接口Condition、对应注解Conditional及其一些默认实现


      1、通过实现Condition接口和添加Conditional注解实现springboot的自动装配

      有时候我们需要根据条件自动装配一些bean,比如根据当前运行的文件是utf-8还是gbk编码来绝定装配哪个bean,请看下面示例,装配了utf8的bean

      pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.edu.spring</groupId>
        <artifactId>springboot</artifactId>
        <version>1.0.0</version>
        <packaging>jar</packaging>
    
        <name>springboot</name>
        <!-- FIXME change it to the project's website -->
        <url>http://www.example.com</url>
        
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.1.6.RELEASE</version>
                    <scope>import</scope>
                    <type>pom</type>
                </dependency>
            </dependencies>
        </dependencyManagement>
        
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
        </dependencies>
    
    </project>
    View Code

      EncodingConvert.java,接口

    package com.edu.spring.springboot;
    
    public interface EncodingConvert {
    
    }
    View Code

      GBKEncodingConvert.java,实现类1

    package com.edu.spring.springboot;
    
    public class GBKEncodingConvert implements  EncodingConvert {
    
    }
    View Code

      UTF8EncodingConvert.java,实现类2

    package com.edu.spring.springboot;
    
    public class UTF8EncodingConvert implements EncodingConvert {
    
    }
    View Code

      GBKCondition.java,实现Condition接口

    package com.edu.spring.springboot;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class GBKCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
            // TODO Auto-generated method stub
            String encoding=System.getProperty("file.encoding");
            if(encoding!=null){
                return "gbk".equals(encoding.toLowerCase());
            }
            return false;
        }
    
    }
    View Code

      UTF8Condition.java,实现Condition接口

    package com.edu.spring.springboot;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class UTF8Condition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
            // TODO Auto-generated method stub
            String encoding=System.getProperty("file.encoding");
            if(encoding!=null){
                return "utf-8".equals(encoding.toLowerCase());
            }
            return false;
        }
    
    }
    View Code

      EncodingConvertConfig.java,创建bean

    package com.edu.spring.springboot;
    
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    
    @SpringBootConfiguration
    public class EncodingConvertConfig {
    
        @Bean
        @Conditional(UTF8Condition.class)
        public  EncodingConvert createUTF8EncodingConvert(){
            return new UTF8EncodingConvert();
        }
        
        @Bean
        @Conditional(GBKCondition.class)
        public  EncodingConvert createGBKEncodingConvert(){
            return new GBKEncodingConvert();
        }
    }
    View Code

      App.java

    package com.edu.spring.springboot;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class App 
    {
        public static void main( String[] args )
        {
            ConfigurableApplicationContext context=SpringApplication.run(App.class,args);
            System.out.println(context.getBeansOfType(EncodingConvert.class));
            context.close();
        }
    }
    View Code

      运行结果如下:

       总结:@Conditional注解与Condition接口要一块使用,Condition接口实现类中的matches方法返回true时,@Conditional标记的bean才会装配。

            @Conditional注解可以加在配置类上,表明该配置类中装配的bean都需要满足返回true的条件。

                  @Conditional注解可以添加多个类,表明要同时满足多个条件才会装配,如@Conditional({UTF8Condition.class,GBKCondition.class})。

    2、Conditional的一些默认实现注解

      (1)@ConditionalOnProperty:根据配置文件中的属性装配bean。如下,配置文件中存在runnable.enble,且值为true时装配

      application.properties

    runnable.enble=true
    View Code

      UserConfig.java

    package com.edu.spring.springboot;
    
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootConfiguration
    public class UserConfig {
        
        @Bean
        @ConditionalOnProperty(name="runnable.enble",havingValue="true")
        public Runnable createRunnable (){
            return () -> {};
        }
    }
    View Code

      App.java

    package com.edu.spring.springboot;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.ConfigurableApplicationContext;
    
    @SpringBootApplication
    public class App 
    {
        public static void main( String[] args )
        {
            ConfigurableApplicationContext context=SpringApplication.run(App.class,args);
            System.out.println(context.getBeansOfType(Runnable.class));
            context.close();
        }
    }
    View Code

      运行结果如下:

       说明:如果改为runnable.enble=false,或者删掉该配置,再次运行则不会创建bean。添加matchIfMissing=true,即便是属性不存在,运行也会创建bean

      (2)@ConditionalOnClass:classpath路径中存在指定的类则创建bean,如下:

      pom.xml,添加gson的依赖

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.edu.spring</groupId>
        <artifactId>springboot</artifactId>
        <version>1.0.0</version>
        <packaging>jar</packaging>
    
        <name>springboot</name>
        <!-- FIXME change it to the project's website -->
        <url>http://www.example.com</url>
        
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.1.6.RELEASE</version>
                    <scope>import</scope>
                    <type>pom</type>
                </dependency>
            </dependencies>
        </dependencyManagement>
        
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
            </dependency>
        </dependencies>
    
    </project>
    View Code

      UserConfig.java

    package com.edu.spring.springboot;
    
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootConfiguration
    public class UserConfig {
        
        
        @Bean
        @ConditionalOnClass(name="com.google.gson.Gson")
        public Runnable createRunnable(){
            return () -> {};
        }
    }
    View Code

      运行结果如下:

       创建成功,如果删掉依赖则不会创建。

      (3)@ConditionalOnBean:如果某个bean存在时,则创建bean,如下:

      UserConfig.java

    package com.edu.spring.springboot;
    
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
    import org.springframework.context.annotation.Bean;
    
    @SpringBootConfiguration
    public class UserConfig {
        
        @Bean
        @ConditionalOnBean(name="user")
        public Runnable createRunnable3(){
            return () -> {};
        }
    }
    View Code

      运行如下:不会创建bean

       User.java,创建user

    package com.edu.spring.springboot;
    
    import org.springframework.stereotype.Component;
    
    @Component
    public class User {
    
    }
    View Code

      再次运行,创建成,结果如下:

       (4)@ConditionalOnMissingBean:当bean不存在时创建,与ConditionalOnBean相反。

  • 相关阅读:
    从零搭建Spring Boot脚手架(6):整合Redis作为缓存
    MyBatis初级实战之三:springboot集成druid
    table布局
    【JVM之内存与垃圾回收篇】直接内存
    【JVM之内存与垃圾回收篇】对象实例化内存布局与访问定位
    【JUnit测试】总结
    【JVM之内存与垃圾回收篇】方法区
    【JVM之内存与垃圾回收篇】堆
    【JVM之内存与垃圾回收篇】本地方法栈
    【JVM之内存与垃圾回收篇】本地方法接口
  • 原文地址:https://www.cnblogs.com/javasl/p/11827837.html
Copyright © 2020-2023  润新知