@EnableAutoConfiguration原理简单分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

一、源码分析简述
声明:本人使用的开发工具为IDEA
1、@EnableAutoConfiguration了解

     查看源码,眼睛扫到@Import(AutoConfigurationImportSelector.class),这很关键。注版本1.5是EnableAutoConfigurationImportSelector,该类继承了AutoConfigurationImportSelector。

2、再查看源码AutoConfigurationImportSelector.java,里面用到了方法getCandidateConfigurations()
然后按住Ctrl点进去,查看方法getCandidateConfigurations(),了解他会到classpath下的读取META-INF/spring.factories文件的配置,并返回一个字符串数组。这说明了@EnableAutoConfiguration– 依赖于META-INF/spring.factories配置文件,spring.factories文件中键key为 org.springframework.boot.autoconfigure.EnableAutoConfiguration ,对应的配置项(注:全类名)加载到spring容器。

  • 前提:只有spring.boot.enableautoconfiguration为true(默认为true)的时候,才启用自动配置
  • 该注解@EnableAutoConfiguration还可以进行排除,排除方式有2中,一是根据classes来排除(exclude),二是根据class names(excludeName)来排除
  • 其内部实现的核心关键点有二

          1)ImportSelector 该接口的方法的返回值都会被纳入到spring 的容器管理
          2)SpringFactoriesLoader 该类可以从classpath中搜索META-INF/spring.factories配置文件,并读取配置
    

二、详细步骤
1、创建两个maven Module ,当然你也可以创建一个pom文件主要代码如下

    1)springboot3的maven module 的POM文件
     <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
    </properties>

    <!--spring boot 环境:方法二:依赖管理加上导入import pom。代替继承,注意 [scope,type]标签-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>1.5.10.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--依赖springboot03-core-bean-->
        <dependency>
            <groupId>com.fai</groupId>
            <artifactId>springboot03-core-bean</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
    </dependencies>

    2)springboot3-core-bean的maven module 的POM文件
    <groupId>com.fai</groupId>
    <artifactId>springboot03-core-bean</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
    </dependencies>

2、创建类

2019101710045\_1.png


    1)Car.java
        public class Car {}

    2)CarConfiguration.java
        @Configuration
        public class CarConfiguration {
            @Bean
            public Car getCar() {
                return new Car();
            }
        }

    3)Music.java
        public class Music {}

    4)RunnableConfiguration.java
        /**
         * Runnable配置类
         */
        @Configuration
        public class RunnableConfiguration {
            @Bean
            public Runnable getRunnable1() {
                return () -> {};
            }
        }

    5)META-INF/spring.factories
        #查看@EnableAutoConfiguration 注解源码,--"spring.boot.enableautoconfiguration";
        #默认true . 如果改成false,EnableAutoConfiguration注解不起作用
        spring.boot.enableautoconfiguration=true

    6)测试
        @EnableAutoConfiguration    // 根据应用所声明的依赖来对Spring框架进行自动配置
        // 根据class排除
        //@EnableAutoConfiguration(exclude = {CarConfiguration.class,Music.class})
        // 根据class names排除,全类名
        //@EnableAutoConfiguration(excludeName = {"com.fai.bean.RunnableConfiguration"})
        @ComponentScan
        public class App {
        public static void main(String[] args) {
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);

        // 获取Runnable 类对象的实例
        // System.out.println(context.getBean(Runnable.class));
        System.out.println(context.getBeansOfType(Runnable.class));

        // 获取Car 类的Bean
        System.out.println(context.getBeansOfType(Car.class));

        // 获取Music 类的Bean
        System.out.println(context.getBeansOfType(Music.class));

        context.close();
        }
    }

    7)在测试中,更改配置文件application.properties中的spring.boot.enableautoconfiguration的值为false后,获取不到Bean
        #查看@EnableAutoConfiguration 注解源码,"spring.boot.enableautoconfiguration";
        #默认true,如果改成false,EnableAutoConfiguration注解不起作用
        spring.boot.enableautoconfiguration=false

在第7)的改为false测试结果如下图,是空的。如果用getBean方法获得Bean,会报错,所以呀用的getBeansOfType方法。
2019101710045\_2.png

三、附上关键源码
1、@EnableAutoConfiguration 注解
@SuppressWarnings(“deprecation”)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class) // 1.5版本,我用的
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、EnableAutoConfigurationImportSelector 源码
@Deprecated
public class EnableAutoConfigurationImportSelector

        extends AutoConfigurationImportSelector {

    @Override
    protected boolean isEnabled(AnnotationMetadata metadata) {
        if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {
            return getEnvironment().getProperty(
                    EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,
                    true);
        }
        return true;
    }

}

3、EnableAutoConfigurationImportSelector 的父类AutoConfigurationImportSelector 源码关键方法摘要
@Override

    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) { // 配置文件中的默认配置为true,我改过false的那个
            return NO_IMPORTS;
        }
        try {
            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                    .loadMetadata(this.beanClassLoader);
            AnnotationAttributes attributes = getAttributes(annotationMetadata);
            List<String> configurations = getCandidateConfigurations(annotationMetadata,
                    attributes);
            configurations = removeDuplicates(configurations);
            configurations = sort(configurations, autoConfigurationMetadata);
            Set<String> exclusions = getExclusions(annotationMetadata, attributes);
            checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = filter(configurations, autoConfigurationMetadata);
            fireAutoConfigurationImportEvents(configurations, exclusions);
            return configurations.toArray(new String[configurations.size()]);
        }
        catch (IOException ex) {
            throw new IllegalStateException(ex);
        }
    }

来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » @EnableAutoConfiguration原理简单分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏