zoukankan      html  css  js  c++  java
  • 【Springboot】Springboot自动装配原理

    1.核心注解就是 EnableAutoConfiguration  该注解会激活SpringBoot的自动装配功能:

    代码如下:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.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 {};
    
    }

    2.其中在 EnableAutoConfiguration 注解之上,还被 @Import(AutoConfigurationImportSelector.class)和 AutoConfigurationPackage修饰,

      @Import的作用就是用来导入配置类或者一些需要前置加载的类:

      @Import支持三种类导入方式:

      第一种:

        @import+@Configuration的 的实现

      第二种

        @import+ImportSelector接口 的实现

      第三种

        @import+ImportBeanDefinitionRegistrar  的实现

      

      SpringBoot自动装配使用的是第二种方式:

    3.其中核心的加载器 AutoConfigurationImportSelector.class 部分如下

    public class AutoConfigurationImportSelector
            implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
            BeanFactoryAware, EnvironmentAware, Ordered {
    
        private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();
    
        private static final String[] NO_IMPORTS = {};
    
        private static final Log logger = LogFactory
                .getLog(AutoConfigurationImportSelector.class);
    
        private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
    
        private ConfigurableListableBeanFactory beanFactory;
    
        private Environment environment;
    
        private ClassLoader beanClassLoader;
    
        private ResourceLoader resourceLoader;
    
        @Override
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            }
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
            AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
                    autoConfigurationMetadata, annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    
        /**
         * Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
         * of the importing {@link Configuration @Configuration} class.
         * @param autoConfigurationMetadata the auto-configuration metadata
         * @param annotationMetadata the annotation metadata of the configuration class
         * @return the auto-configurations that should be imported
         */
        protected AutoConfigurationEntry getAutoConfigurationEntry(
                AutoConfigurationMetadata autoConfigurationMetadata,
                AnnotationMetadata annotationMetadata) {
            if (!isEnabled(annotationMetadata)) {
                return EMPTY_ENTRY;
            }
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            List<String> configurations = getCandidateConfigurations(annotationMetadata,
                    attributes);
            configurations = removeDuplicates(configurations);
            Set<String> exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = filter(configurations, autoConfigurationMetadata);
            fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationEntry(configurations, exclusions);
        }

      在该导入类中,其中selectImpots是具体导入的方法,更深一层的方法  getCandidateConfigurations()便是用来获取需要被自动装配的类的全限定类名信息集合;这些集合信息也就是SpringBoot自动装配的一些组件,这些

    组件会,等待实例化 后被加入到Spring的IOC容器中(该类名信息集合存放在META-INF/spring.factories 中)

       这些自动装配的类也不是完全会被实例化加入到IOC容器中,例如  AopAutoConfiguration 该类就依赖于条件注解  @ ConditionalOnClass 和  @ConditionalOnProperty

    这也就解释了为什么在SpringBoot项目中 如果添加了jdbc的starter后.如果没有在配置文件中配置数据库的信息 程序启动会报错的原因;

    @Configuration
    @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
            AnnotatedElement.class })
    @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true",
            matchIfMissing = true)
    public class AopAutoConfiguration {
    
        @Configuration
        @EnableAspectJAutoProxy(proxyTargetClass = false)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
                havingValue = "false", matchIfMissing = false)
        public static class JdkDynamicAutoProxyConfiguration {
    
        }
    
        @Configuration
        @EnableAspectJAutoProxy(proxyTargetClass = true)
        @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class",
                havingValue = "true", matchIfMissing = true)
        public static class CglibAutoProxyConfiguration {
    
        }
    
    }

      

  • 相关阅读:
    bat %n 判断传入的参数值和使用注意
    git ls-remote url,判断 url 是否存在
    bat 读取 ini 文件
    bat 提示窗口,带换行
    python .pth 文件 和 site 模块
    python Pillow 图片处理模块,好强大有没有
    Python 获取 exe 的 icon 并且保存
    git 判断路径是否是 git 仓库
    Python 去除字符串中的空行
    Android平台程序崩溃的类型及原因列举
  • 原文地址:https://www.cnblogs.com/july-sunny/p/13566010.html
Copyright © 2011-2022 走看看