转载

Sring Boot 自动装配

title: Sring Boot 自动装配 date: 2019-07-18 categories:

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

SpringBoot和新特性笔记。

  • 注解模式装配

    @sevice @Conrtroller @Repository @Component

    这几个注解在 Srping源码 的文章中已经将结果了,这里就不在赘述了。

  • 条件(Condition)装配

    Condition 注解作为条件,如果符合条件则将 bean 注入到 IOC 中,反之则不注入,实际是使用 @Conditional 注解来实现,继承 Condition 接口,通过 matches 方法进行逻辑判断是否符合条件。

    1: 创建ConditionOnSysProperty注解

    /**
     * @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所需要的条件 SysPropertyCondition

    /**
     * @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测试

    /**
     * @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) 进行灵活的动态判断

    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
    复制代码
原文  https://juejin.im/post/5d53c50e51882562945d1121
正文到此结束
Loading...