zoukankan      html  css  js  c++  java
  • [读书笔记] 二、条件注解@Conditional,组合注解,元注解

    一、条件注解@Conditional,组合注解,元注解

    1.

    @Conditional:满足特定条件创建一个Bean,SpringBoot就是利用这个特性进行自动配置的。

    例子:

    首先,两个Condition,判断当前系统是否是Windows或者Linux(True False)

    然后,2个ListService实现类,表明不同系统下的ListService实现。

    主要,ConditionConfig使用了Java配置与@Conditional注解,根据LinuxCondition,或者WindowsCondition作为判断条件

    产生相应与系统匹配的实现类。

    最后,App.java 测试成功。

    package com.springboot.springboot_test2_1;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class LinuxCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
            return arg0.getEnvironment().getProperty("os.name").contains("Linux");
        }
    
    }
    LinuxCondition.java
    package com.springboot.springboot_test2_1;
    
    import org.springframework.context.annotation.Condition;
    import org.springframework.context.annotation.ConditionContext;
    import org.springframework.core.type.AnnotatedTypeMetadata;
    
    public class WindowsCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
            return arg0.getEnvironment().getProperty("os.name").contains("Windows");
        }
    
    }
    WindowsCondition.java
    package com.springboot.springboot_test2_1;
    
    public interface ListService {
        public String showListCmd();
    }
    ListService.java
    package com.springboot.springboot_test2_1;
    
    public class LinuxListService implements ListService{
    
        @Override
        public String showListCmd() {
            return "ls";
        }
        
    }
    LinuxListService.java
    package com.springboot.springboot_test2_1;
    
    public class WindowsListService implements ListService{
    
        @Override
        public String showListCmd() {
            return "dir";
        }
        
    }
    WindowsListService.java
    package com.springboot.springboot_test2_1;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Conditional;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class ConditionConfig {
    
        @Bean
        @Conditional(WindowsCondition.class)
        public ListService windowsListService() {
            return new WindowsListService();
        }
    
        @Bean
        @Conditional(LinuxCondition.class)
        public ListService linuxListService() {
            return new LinuxListService();
        }
    
    }
    ConditionConfig.java
    package com.springboot.springboot_test2_1;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    
    /**
     * Hello world!
     * 
     */
    public class App {
        public static void main(String[] args) {
            
            ApplicationContext context = new AnnotationConfigApplicationContext(
                    ConditionConfig.class);
            
            ListService ls = context.getBean(ListService.class);
            System.out.println(context.getEnvironment().getProperty("os.name")
                    + "系统下的列表命令为:" + ls.showListCmd());
        }
    }
    App.java

    2.

    元注解:可以注解到别的注解上的注解。

    组合注解:元注解+被注解=组合注解。

    例子:

    package com.springboot.springboot_test2_1;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    @ComponentScan
    public @interface testConfig {
        String[] value() default{};
    }
    testConfig.java

    二、通过条件注解@Conditional,组合注解,元注解理解SpringBoot的自动配置

    @SpringBootApplication,源码:

    @Target({java.lang.annotation.ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters={@org.springframework.context.annotation.ComponentScan.Filter(type=org.springframework.context.annotation.FilterType.CUSTOM, classes={org.springframework.boot.context.TypeExcludeFilter.class}), @org.springframework.context.annotation.ComponentScan.Filter(type=org.springframework.context.annotation.FilterType.CUSTOM, classes={AutoConfigurationExcludeFilter.class})})
    public @interface SpringBootApplication
    {
      @AliasFor(annotation=EnableAutoConfiguration.class, attribute="exclude")
      Class<?>[] exclude() default {};
      
      @AliasFor(annotation=EnableAutoConfiguration.class, attribute="excludeName")
      String[] excludeName() default {};
      
      @AliasFor(annotation=ComponentScan.class, attribute="basePackages")
      String[] scanBasePackages() default {};
      
      @AliasFor(annotation=ComponentScan.class, attribute="basePackageClasses")
      Class<?>[] scanBasePackageClasses() default {};
    }
    SpringBootApplication源码

    它的核心功能是由@EnableAutoConfiguration注解提供的,

    @EnableAutoConfiguration,源码:

    @SuppressWarnings("deprecation")
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(EnableAutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    
        String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
    
        /**
         * Exclude specific auto-configuration classes such that they will never be applied.
         * @return the classes to exclude
         */
        Class<?>[] exclude() default {};
    
        /**
         * Exclude specific auto-configuration class names such that they will never be
         * applied.
         * @return the class names to exclude
         * @since 1.3.0
         */
        String[] excludeName() default {};
    
    }
    EnableAutoConfiguration源码

    @EnableAutoConfiguration其中的@AutoConfigurationPackage,会扫描/META-INF/spring.factories文件中的jar包,

    spring.factories文件如下:

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
    org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
    org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
    org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
    org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
    org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
    org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\

    ……

    2、核心注解

    spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:

    @ConditionalOnBean:当容器里有指定Bean的条件下

    @ConditionalOnClass:当类路径下有指定类的条件下

    @ConditionalOnExpression:基于SpEL表达式作为判断条件

    @ConditionalOnJava:基于JV版本作为判断条件

    @ConditionalOnJndi:在JNDI存在的条件下差在指定的位置

    @ConditionalOnMissingBean:当容器里没有指定Bean的情况下

    @ConditionalOnMissingClass:当类路径下没有指定类的条件下

    @ConditionalOnNotWebApplication:当前项目不是Web项目的条件下

    @ConditionalOnProperty:指定的属性是否有指定的值

    @ConditionalOnResource:类路径是否有指定的值

    @ConditionalOnSingleCandidate:当指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean

    @ConditionalOnWebApplication:当前项目是Web项目的条件下。

    上面@ConditionalOnXXX都是组合@Conditional元注解,使用了不同的条件Condition

  • 相关阅读:
    【Linux】grep or
    win10查看WiFi密码
    【WPF】Border有显示模糊的情况
    【Spark】配置项spark.network.timeout 的单位是什么
    【Linux】free命令中 free与 available 的区别
    Spark2.3配置项
    java获取jar包执行路径
    编译 thrift-0.14.2 的 C++ 版本
    拉端保障方案
    编译运行ebpf代码的流水账
  • 原文地址:https://www.cnblogs.com/javapath/p/6814016.html
Copyright © 2011-2022 走看看