Sring Boot 自動裝配


title: Sring Boot 自動裝配 date: 2019-07-18 categories:java

  • SpringBoot tags:
  • SpringBoot
  • @EnableAutoConfiguration
  • @Condition
  • spring.factories top: true toc: true

SpringBoot和新特性筆記。spring

  • 註解模式裝配

    @sevice @Conrtroller @Repository @Componentspringboot

    這幾個註解在Srping源碼的文章中已經將結果了,這裏就不在贅述了。ide

  • 條件(Condition)裝配

    Condition 註解做爲條件,若是符合條件則將bean注入到IOC中,反之則不注入,實際是使用 @Conditional註解來實現,繼承 Condition 接口,經過 matches 方法進行邏輯判斷是否符合條件。測試

    1: 建立ConditionOnSysProperty註解ui

    /** * @Auther: lantao * @Date: 2019-07-18 17:52 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Documented
    @Conditional({SysPropertyCondition.class})
    public @interface ConditionOnSysProperty {
    
        String value() default "lantao";
    }
    複製代碼

    2:建立@Condtional所須要的條件 SysPropertyConditionspa

    /** * @Auther: lantao * @Date: 2019-07-18 17:52 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    public class SysPropertyCondition implements Condition {
    
        /** * 匹配方法 * * @param context * @param metadata * @return */
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            // 獲取 ConditionOnSysProperty 註解的屬性
            Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionOnSysProperty.class.getName());
    
            String value = String.valueOf(attributes.get("value"));
    
            // 獲取本機的user.name值
            String propertieValue = System.getProperties().get("user.name").toString();
    
            // 對比
            return value.equals(propertieValue);
        }
    }
    複製代碼

    3:建立COnditionBootStrap測試code

    /** * @Auther: lantao * @Date: 2019-07-18 17:44 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    public class ConditionBootStrap {
    
        @Bean
        // 這了由於value是lantao, 正好user.name也是lantao,因此條件成立,會將bean注入到ioc中
        @ConditionOnSysProperty(value = "lantao")
        private String helloWorld() {
            return "Hello World ! Condition";
        }
    
    
        public static void main(String[] args) {
            // 這種方式能夠不使用 SpringBootApplication 註解
            ConfigurableApplicationContext context = new SpringApplicationBuilder(ConditionBootStrap.class).run(args);
    
            // 獲取名爲 helloWorld 的Bean,判斷 ConditionOnSysProperty 條件是否生效
            String helloWorld = context.getBean("helloWorld", String.class);
    
            System.out.println(helloWorld);
    
            // 關閉
            context.close();
        }
    }
    
    結果:
    Hello World ! Condition
    複製代碼
  • @Enable 模塊裝配

    Eanble註解內部使用@Importbean注入到ioc中,@import註解中能夠直接放入bean,也能夠作更靈活的配置,使用繼承了ImportSeletor接口的bean,能夠根據@Enable註解的屬性(attrbutes)進行靈活的動態判斷cdn

    1: 建立 EnableHelloWorld繼承

    /** * @Auther: lantao * @Date: 2019-07-18 18:03 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    // 直接使用沒法靈活判斷
    //@Import(TestConfiguration.class)
    
    // 使用 HelloWorldImportSeletor 能夠有更靈活的判斷
    @Import(HelloWorldImportSeletor.class)
    public @interface EnableHelloWorld {
    
        String name() default "lantao";
    }
    複製代碼

    2: 建立TestConfiguration和Test1Configuration

    public class TestConfiguration {
        @Bean
        private String helloWorld() {
            return "hello World! Enable";
        }
    }
    
    public class Test1Configuration {
        @Bean
        public String buzhidao() {
            return "不知道";
        }
    }
    
    複製代碼

    3: 建立HelloWorldImportSeletor

    /** * @Auther: lantao * @Date: 2019-07-19 09:55 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    public class HelloWorldImportSeletor implements ImportSelector {
    
        @Override
        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
            // 獲取EnableHelloWorld註解的屬性
            Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableHelloWorld.class.getName());
            // 根據attributes 靈活判斷注入那個bean
            if ("lantao".equals(attributes.get("name"))) {
                System.out.println(TestConfiguration.class.getName());
                return new String[]{TestConfiguration.class.getName()};
            }
            System.out.println(TestConfiguration.class.getName());
            return new String[]{Test1Configuration.class.getName()};
        }
    }
    複製代碼

    4:建立bootStrap測試

    /** * @Auther: lantao * @Date: 2019-07-18 18:04 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    @EnableHelloWorld
    //@EnableHelloWorld(name = "buzhidao")
    public class EnableBootStrap {
        public static void main(String[] args) {
    
            // 這種方式能夠不使用 SpringBootApplication 註解
            ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableBootStrap.class).run(args);
    
            // 獲取名爲 helloWorld 的Bean,判斷 ConditionOnSysProperty 條件是否生效
            String helloWorld = context.getBean("helloWorld", String.class);
          // 這裏能夠獲取 bean名稱爲 'buzhidao',須要註解@EnableHelloWorld(name = "buzhidao"),
          // 由於@EnableHelloWorld的name默認值是lantao,符合Condition的條件判斷
    // String helloWorld = context.getBean("buzhidao", String.class);
    
            System.out.println(helloWorld);
    
            // 關閉
            context.close();
        }
    }
    
    結果:
    hello World! Enable
    複製代碼
  • 工廠模式裝配

    自定義spring.factories,工廠模式裝配能夠自定義starter。

    1: 建立SpringFactoriesConfiguration

    /** * @Auther: lantao * @Date: 2019-07-22 10:10 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */ 
    @EnableHelloWorld
    @ConditionOnSysProperty(value = "lantao")
    @Configuration
    public class SpringFactoriesConfiguration {
        // 這裏沒有寫 bean 的注入,直接引用 Condition 和 eanble 模塊註解。
    
        // eanble註解內部使用import將bean注入到ioc中,@import註解中能夠直接放入bean,也能夠作更靈活的配置使用繼承了ImportSeletor接口的bean,
        // 能夠根據enable註解的屬性(attrbutes)進行靈活的動態判斷
    
        // Condition 註解做爲條件,若是符合條件則將bean注入到IOC中,反之則不注入,實際是使用 @Conditional註解來實現,經過繼承 Condition 接口,
        // 經過 matches 方法進行邏輯判斷是否符合條件。
    }
    複製代碼

    2: 建立 META-INF/spring.factories

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.lantao.springboot_leran.spring_factories_leran.config.SpringFactoriesConfiguration
    複製代碼

    3: 建立 SpringFactoriesBootStrap 引導類

    /** * @Auther: lantao * @Date: 2019-07-19 16:01 * @Company: 隨行付支付有限公司 * @maill: lan_tao@suixingpay.com * @Description: TODO */
    @EnableAutoConfiguration
    public class SpringFactoriesBootStrap {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext context = new SpringApplicationBuilder(SpringFactoriesBootStrap.class).run(args);
            String helloWorld = context.getBean("helloWorld", String.class);
            System.out.println(helloWorld);
            context.close();
        }
    }
    
    結果:
    hello World! Enable
    複製代碼

相關文章
相關標籤/搜索