美文网首页
SpringBoot2.0深度实践学习笔记(四)之Spring

SpringBoot2.0深度实践学习笔记(四)之Spring

作者: Sam_L | 来源:发表于2019-04-23 09:35 被阅读0次

    【定义】
    在 Spring Boot 场景下,基于约定大于配置的原则,实现 Spring 组件自动装配的目的。

    【底层装配技术方式】
    (1)Spring 模式注解装配
    (2)Spring @Enable 模块装配
    (3)Spring 条件装配装配
    (4)Spring 工厂加载机制---也是spring里面的一个机制
    实现类: SpringFactoriesLoader---装载配置方法,称为spring的工厂
    配置资源: META-INF/spring.factories---配置了很多自动装配的东西
    结合工厂加载机制实现配置化的加载自动化装配的实现

    【实现方式:】
    1、激活自动装配 @EnableAutoConfiguration-- 一般在引导类进行标注,
    有的时候在引导类看不到@EnableAutoConfiguration注解,是因为在@SpringBootApplication里面包含了这部分内容
    就是说当标注了@SpringBootApplication就是标注了@EnableAutoConfiguration

    1.png
    2、实现自动装配 XXXAutoConfiguration
    要实现一个XXXAutoConfiguration实现类
    可以将模式注解装配、@Enable模块,条件装配,三种方式整合在一起
    3、配置自动装配实现 - META-INF/spring.factories

    @since 3.2提出的
    通过配置的方式把AutoConfiguration的实现配置到 META-INF/spring.factories文件里,通过这个文件写到classpath目录里面来,jar包会加载。
    通过KV方式配置 ------key是工厂方法,有个loadFactories方法它的参数factoryClass就是工厂方法,是全类名,值是实现类的全类名,
    配置的时候要注意格式,参照spring.factories 源码格式,\换行,空格去掉。

    /**
         * Load and instantiate the factory implementations of the given type from
         * {@value #FACTORIES_RESOURCE_LOCATION}, using the given class loader.
         * <p>The returned factories are sorted through {@link AnnotationAwareOrderComparator}.
         * <p>If a custom instantiation strategy is required, use {@link #loadFactoryNames}
         * to obtain all registered factory names.
         * @param factoryClass the interface or abstract class representing the factory
         * @param classLoader the ClassLoader to use for loading (can be {@code null} to use the default)
         * @throws IllegalArgumentException if any factory implementation class cannot
         * be loaded or if an error occurs while instantiating any factory
         * @see #loadFactoryNames
         */
        public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
            Assert.notNull(factoryClass, "'factoryClass' must not be null");
            ClassLoader classLoaderToUse = classLoader;
            if (classLoaderToUse == null) {
                classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
            }
            List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
            }
            List<T> result = new ArrayList<>(factoryNames.size());
            for (String factoryName : factoryNames) {
                result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
            }
            AnnotationAwareOrderComparator.sort(result);
            return result;
        }
    

    【spring.factories 源码】
    激活自动装配EnableAutoConfiguration,下面的这些就会被组装

    # 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.CloudServiceConnectorsAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
    org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
    org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
    ……………………
    

    【小栗子---结合之前的学习】

    1. 激活自动装配 - @EnableAutoConfiguration
      bootstrap包下面----新建引导类EnableAutoConfigurationBootstrap
      标注@EnableAutoConfiguration
    @EnableAutoConfiguration
    public class EnableAutoConfigurationBootstrap {
    
        public static void main(String[] args) {
    
            ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableAutoConfigurationBootstrap.class)
                    .web(WebApplicationType.NONE)
                    .run(args);
    
            //关闭上下文
            context.close();
        }
    }
    
    1. 实现自动装配 - XXXAutoConfiguration
      configuration包下面新建HelloWorldAutoConfiguration实现类
    /**
     * Hello World 自动装配
     */
    @Configuration   //Spring 模式注解装配
    @EnableHelloWorld   //Spring @Enable模块装配
    @ConditionalOnSystemProperty(name="user.name",value = "Lenovo") //条件装配
    public class HelloWorldAutoConfiguration {
    }
    

    说明:
    还记得之前学过的Spring模式注解吗?
    还记得之前学过的@Enable模块装配吗?--这里采用间接的方式
    还记得之前学过的条件装配吗?
    好吧,忘记了再瞅几眼~~~

    3. 配置自动装配实现 - META-INF/spring.factories ---通过KV方式配置

    resources下新建-META-INF目录---新建spring.factories文件
    builde一下,会在target下面看到这个文件


    2.png

    参照源码格式进行配置
    META-INF/spring.factories

    # 自动装配
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    com.cbt.diveinspringboot.configuration.HelloWorldAutoConfiguration
    

    【说明】
    HelloWorldAutoConfiguration

    • 条件判断 :条件是满足的----- user.name == "Lenovo"
    • 模式注解: @Configuration
    • @Enable模块:
      @EnableHelloWorld ->加载 HelloWorldImportSelector ->Selector 加载HelloWorldConfiguration - > HelloWorldConfiguration会自动生成 helloWorld bean
      引导类启动后这个bean就会被装载掉

    也就是说:
    模块装配的时候,前面的条件都满足就会引导出@EnableHelloWorld ->加载 HelloWorldImportSelector ->加载HelloWorldConfiguration - > helloWorld bean

    实现了模式注解、@Enable模块、条件装配三种方式整合在一起

    4、同样的方式可以对bean进行检查

    完善引导类

    /**
     * {@link @EnableAutoConfiguration}引导类
     */
    @EnableAutoConfiguration
    public class EnableAutoConfigurationBootstrap {
    
        public static void main(String[] args) {
    
            ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableAutoConfigurationBootstrap.class)
                    .web(WebApplicationType.NONE)
                    .run(args);
    
            //helloWorld Bean是否存在
            String helloWorld = context.getBean("helloWorld", String.class);
    
            System.out.println("helloWorld Bean : " + helloWorld);
    
            //关闭上下文
            context.close();
        }
    }
    

    运行:


    3.png

    SpringBoot自动化装配不是SpringBoot的一个特性,是基于Spring Framework的实现。
    只是在执行的时候增加了META-INF---spring.factories
    所有的API包括条件装配,@Enable模块、模式注解都是spring的一个接口

    这个其实就是属于Spring Annotation Programming Model的编程模型,这个编程模型决定了后面springboot的很多特性。

    相关文章

      网友评论

          本文标题:SpringBoot2.0深度实践学习笔记(四)之Spring

          本文链接:https://www.haomeiwen.com/subject/ukrmgqtx.html