走向自动装配(来自Spring Boot 2.0深度实践之核心技术篇的学习)

走向自动装配

  • 手动装配 Spring Framework
  1. 手动装配 - 模式注解装配
    • 注解的 “派生性”
      被@ Component直接注解的类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Component
public @interface StudyOneAnnotation {
    String value() default "";
}
  • 注解的 “层次性”
       间接被@ Component注解的类

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Documented

@StudyOneAnnotation

public @interface StudyTwoAnnotation {

    String value() default "";

}

         测试:

                   和使用@Component一样,注解到Class上面。然后进行被扫描就ok。

                   @StudyTwoAnnotation也可以换成@StudyOneAnnotation一样的效果

@StudyTwoAnnotation

public class StudyAutoConfig {

    public String study(){

        return "hello study auto configuration";

    }

}

 

         结果:

                  

@ComponentScan("com.wangkun.springBootStudy.configration")

public class StudyAutoConfigBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context =

                new SpringApplicationBuilder(StudyAutoConfigBootstrap.class)

                .web(WebApplicationType.NONE)

                .run(args);

 

        StudyAutoConfig study = context.getBean("studyAutoConfig", StudyAutoConfig.class);

        System.out.println(study.study());

        //关闭

        context.close();

    }

}

           

  • 其实我们写的 ”派生性” 在我们Spring 的@Configuration中得到充分的体现

@configuration源码

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Component

public @interface Configuration {

        

@AliasFor(annotation = Component.class)

         String value() default "";

}

              

       给自己留个任务,为什么我们写的@Configuration中的@Bean根本不用我们扫描,怎么改变以前的配置的?

 

  1. 手动装配 - @Enable模块装配(将功能组合到一个注解上进行独立单元)
    • 注解方式(在我们的驱动Class上面加上@EnableXxx注解则可以导入想要的Bean)

EnableXXX 注解

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Documented

@Import(StudyAutoConfig.class)

public @interface EnableStudyAutoConfig {

 

}

EnableXXXConfiguration 类

@Configuration

public class StudyAutoConfig {

    @Bean

    public String study(){

        return "hello study auto configuration";

    }

}

驱动类(@EnableStudyAutoConfig注解到Bootstrap

@EnableStudyAutoConfig

public class StudyAutoConfigBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context =

                new SpringApplicationBuilder(StudyAutoConfigBootstrap.class)

                .web(WebApplicationType.NONE)

                .run(args);

 

        String study = context.getBean("study", String.class);

        System.out.println(study);

 

        //关闭

        context.close();

    }

}

  • 编程方式(富有弹性的导入,按照选择导入进想要的配置)

EnableXXX

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Documented

@Import(StudyAutoImportSelector.class)

public @interface EnableSelectorStudyAutoAnnotation {

}

EnableImportSelector

         实现ImportSelector接口完成方法的重写,返回类型是String[],也就是你的配置类的返回集合。这里写出了,两个配置类。并且该方法可以根据自己的条件判断什么条件下返回什么配置类。

public class StudyAutoImportSelector implements ImportSelector {

    @Override

    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[]{StudyAutoConfig.class.getName() ,

                        HelloWorldConfiguration.class.getName()};

    }

}

EnableConfiguration

@Configuration

public class StudyAutoConfig {

    @Bean

    public String study(){

        return "hello study auto configuration";

    }

}

@Configuration

public class HelloWorldConfiguration {

    @Bean

    public String hello(){

        return "hello world 2018!";

    }

}

 驱动类

@EnableSelectorStudyAutoAnnotation

public class StudyAutoConfigBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context =

                new SpringApplicationBuilder(StudyAutoConfigBootstrap.class)

                .web(WebApplicationType.NONE)

                .run(args);

 

        String study = context.getBean("study", String.class);

        System.out.println(study);

 

        String hello = context.getBean("hello",String.class);

        System.out.println(hello);

 

        //关闭

        context.close();

    }

}

      

  1. 手动装配 – Spring条件装配
    • Profile

Java7JiSuan.class 针对Java8采用的计算总和的服务

@Profile("Java7")

@Service("jiSuan")

public class Java7JiSuan implements JiSuan{

    @Override

    public int add(Integer... figures) {

        System.out.println("使用for循环进行数字的累加!");

        int sum = 0;

 

        for(Integer figure : figures){

            sum += figure;

        }

 

        return sum;

    }

}

 

Java8JiSuan.class 针对Java8采用的计算总和的服务

@Profile("Java8")

@Service("jiSuan")

public class Java8JiSuan implements JiSuan{

        @Override

        public int add(Integer... figures) {

            System.out.println("使用lambda循环进行数字的累加!");

            int sum = Stream.of(figures).reduce(0,Integer::sum);

            return sum;

        }

}

驱动类

         启动程序的时候选择Profile的测试版本

@ComponentScan("com.wangkun.springBootStudy.service")

public class StudyAutoConfigBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context =

                new SpringApplicationBuilder(StudyAutoConfigBootstrap.class)

                .web(WebApplicationType.NONE)

                .profiles("Java8")

                .run(args);

 

        JiSuan jiSuan = context.getBean("jiSuan", JiSuan.class);

        int add = jiSuan.add(1, 2, 3, 4, 5, 6, 7, 8, 9);

        System.out.println(add);

 

        //关闭

        context.close();

    }

}

       

  • Conditional

XXXConditionAnnotation

         我们这里想演示在方法上面创建一个Bean,所以使用的是方法级别的Target

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

@Conditional(StudyAutoConfigConditional.class)

public @interface StudyAutoConfigConditionAnnotation {

    String name() default "";

    String value() default "";

}

XXXConditional

         实现Condition中的matches方法,可以根据自己的判断条件进行变更。我们这里使用的是取出注解上面的参数和我们系统中的数据进行比对。True则创建Bean,否则不创建Bean。

public class StudyAutoConfigConditional implements Condition {

 

    @Override

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

        Map<String, Object> attrs = metadata.getAnnotationAttributes(StudyAutoConfigConditionAnnotation.class.getName());

        String name = String.valueOf(attrs.get("name"));

        String value = String.valueOf(attrs.get("value"));

 

        String property = System.getProperty(name);

 

        return value.equals(property);

    }

}

驱动类

public class StudyAutoConfigBootstrap {

    @Bean

    @StudyAutoConfigConditionAnnotation(name = "user.name",value = "troila")

    private String hello(){

        return "hello condition";

    }

 

    public static void main(String[] args) {

        ConfigurableApplicationContext context =

                new SpringApplicationBuilder(StudyAutoConfigBootstrap.class)

                .web(WebApplicationType.NONE)

                .profiles("Java8")

                .run(args);

 

        String hello = context.getBean("hello", String.class);

        System.out.println(hello);

 

        //关闭

        context.close();

    }

}

      

  • 自动装配
    • 必要条件
        1. EnableAutoXXX类
        2. Spring.factories
        3. 驱动类
    • 实现

EnableAutoXXX注解

           自动配置将我们上面学到的手动配置全部使用到了。

@Configuration  //模式注解驱动

@EnableStudyAutoConfig  //模块注解驱动

@StudyAutoConfigConditionAnnotation(name = "user.name",value = "troila") //条件驱动

public class EnableAutoConfigStudyAutoConfigConditional {

}

Spring.factories (放到我们resources -> META-INF 下)

对应我们的自动配置的Class,是我们自动配置的关键

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

com.wangkun.springBootStudy.configration.HelloWorldEnableAutoConfiguration,\

com.wangkun.springBootStudy.conditional.EnableAutoConfigStudyAutoConfigConditional

驱动类:

@EnableAutoConfiguration

public class StudyAutoConfigBootstrap {

    public static void main(String[] args) {

        ConfigurableApplicationContext context =

                new SpringApplicationBuilder(StudyAutoConfigBootstrap.class)

                .web(WebApplicationType.NONE)

                .run(args);

 

        String hello = context.getBean("study", String.class);

        System.out.println(hello);

 

        //关闭

        context.close();

    }

}

     

  • 启动流程

@EnableAutoConfiguration  –>  spring.factories  –>  conditional   –>  importselector –>  configuration  –>  hello的Bean

           驱动类被@EnableAutoConfiguration注解,spring去spring.factories中寻找自动配置的类,找到之后查看我们是否符合conditional的条件,如果符合spring去选择符合条件的configuration类,根据我们的需要生成Bean。

 

总结:

         通过了解spring boot的自动化配置,让我对springboot又多了一点的了解,不再迷茫为什么驱动类上要有自动配置注解,不再迷茫为什么@EnableXXX注解配置之后,我们有了那么多的功能。

SpringBoot是企业级开发的整体整合解决方案,特别用于快速构建微服务应用,旨在用最简单的方式让开发人员适应各种开发场景; 本视频着重介绍SpringBoot的使用和内部原理;内容包含微服务概念、配置文件、日志框架的使用、web开发、Thymeleaf模板引擎、Docker容器技术、MyBatis、Spring Data JPA、自定义starter等; 00、尚硅谷_SpringBoot_源码、课件 01、尚硅谷_SpringBoot_入门-课程简介 02、尚硅谷_SpringBoot_入门-Spring Boot简介 03、尚硅谷_SpringBoot_入门-微服务简介 04、尚硅谷_SpringBoot_入门-环境准备 05、尚硅谷_SpringBoot_入门-springboot-helloworld 06、尚硅谷_SpringBoot_入门-HelloWorld细节-场景启动器(starter) 07、尚硅谷_SpringBoot_入门-HelloWorld细节-自动配置 08、尚硅谷_SpringBoot_入门-使用向导快速创建Spring Boot应用 09、尚硅谷_SpringBoot_配置-yaml简介 10、尚硅谷_SpringBoot_配置-yaml语法 11、尚硅谷_SpringBoot_配置-yaml配置文件值获取 12、尚硅谷_SpringBoot_配置-properties配置文件编码问题 13、尚硅谷_SpringBoot_配置-@ConfigurationProperties与@Value区别 14、尚硅谷_SpringBoot_配置-@PropertySource、@ImportResource、@Bean 15、尚硅谷_SpringBoot_配置-配置文件占位符 16、尚硅谷_SpringBoot_配置-Profile多环境支持 17、尚硅谷_SpringBoot_配置-配置文件的加载位置 18、尚硅谷_SpringBoot_配置-外部配置加载顺序 19、尚硅谷_SpringBoot_配置-自动配置原理 20、尚硅谷_SpringBoot_配置-@Conditional&自动配置报告 21、尚硅谷_SpringBoot_日志-日志框架分类和选择 22、尚硅谷_SpringBoot_日志-slf4j使用原理 23、尚硅谷_SpringBoot_日志-其他日志框架统一转换为slf4j 24、尚硅谷_SpringBoot_日志-SpringBoot日志关系 25、尚硅谷_SpringBoot_日志-SpringBoot默认配置 26、尚硅谷_SpringBoot_日志-指定日志文件和日志Profile功能 27、尚硅谷_SpringBoot_日志-切换日志框架 28、尚硅谷_SpringBoot_web开发-简介 29、尚硅谷_SpringBoot_web开发-webjars&静态资源映射规则 30、尚硅谷_SpringBoot_web开发-引入thymeleaf 31、尚硅谷_SpringBoot_web开发-thymeleaf语法 32、尚硅谷_SpringBoot_web开发-SpringMVC自动配置原理 33、尚硅谷_SpringBoot_web开发-扩展与全面接管SpringMVC 34、尚硅谷_SpringBoot_web开发-【实验】-引入资源 35、尚硅谷_SpringBoot_web开发-【实验】-国际化 36、尚硅谷_SpringBoot_web开发-【实验】-登陆&拦截器 37、尚硅谷_SpringBoot_web开发-【实验】-Restful实验要求 38、尚硅谷_SpringBoot_web开发-【实验】-员工列表-公共页抽取 39、尚硅谷_SpringBoot_web开发-【实验】-员工列表-链接高亮&列表完成 40、尚硅谷_SpringBoot_web开发-【实验】-员工添加-来到添加页面 41、尚硅谷_SpringBoot_web开发-【实验】-员工添加-添加完成 42、尚硅谷_SpringBoot_web开发-【实验】-员工修改-重用页面&修改完成 43、尚硅谷_SpringBoot_web开发-【实验】-员工删除-删除完成 44、尚硅谷_SpringBoot_web开发-错误处理原理&定制错误页面 45、尚硅谷_SpringBoot_web开发-定制错误数据 46、尚硅谷_SpringBoot_web开发-嵌入式Servlet容器配置修改 47、尚硅谷_SpringBoot_web开发-注册servlet三大组件 48、尚硅谷_SpringBoot_web开发-切换其他嵌入式Servlet容器 49、尚硅谷_SpringBoot_web开发-嵌入式Servlet容器自动配置原理 50、尚硅谷_SpringBoot_web开发-嵌入式Servlet容器启动原理 51、尚硅谷_SpringBoot_web开发-使用外部Servlet容器&JSP;支持 52、尚硅谷_SpringBoot_web开发-外部Servlet容器启动SpringBoot应用原理 53、尚硅谷_SpringBoot_Docker-简介 54、尚硅谷_SpringBoot_Docker-核心概念 55、尚硅谷_SpringBoot_Docker-linux环境准备 56、尚硅谷_SpringBoot_Docker-docker安装&启动&停止 57、尚硅谷_SpringBoot_Docker-docker镜像操作常用命令 58、尚硅谷_SpringBoot_Docker-docker容器操作常用命令 59、尚硅谷_SpringBoot_Docker-docker安装MySQL 60、尚硅谷_SpringBoot_数据访问-简介 61、尚硅谷_SpringBoot_数据访问-JDBC&自动配置原理 62、尚硅谷_SpringBoot_数据访问-整合Druid&配置数据源监控 63、尚硅谷_SpringBoot_数据访问-整合MyBatis(一)-基础环境搭建 64、尚硅谷_SpringBoot_数据访问-整合MyBatis(二)-注解版MyBatis 65、尚硅谷_SpringBoot_数据访问-整合MyBatis(二)-配置版MyBatis 66、尚硅谷_SpringBoot_数据访问-SpringData JPA简介 67、尚硅谷_SpringBoot_数据访问-整合JPA 68、尚硅谷_SpringBoot_原理-第一步:创建SpringApplication 69、尚硅谷_SpringBoot_原理-第二步:启动应用 70、尚硅谷_SpringBoot_原理-事件监听机制相关测试 71、尚硅谷_SpringBoot_原理-自定义starter
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值