springboot自动装配

2021-02-22  本文已影响0人  小方块886

springboot自动装配重要注解

  1. @EnableAutoConfiguration @Import
    作用:将发现的类交给spring管理,先看一下@import注解在哪里用到
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // springboot启动类中@EnableAutoConfiguration注解中
public @interface EnableAutoConfiguration { // springboot启动类@SpringBootApplication注解中

这里我们开始试验一下import注解的作用
先创建一个demot类

//@Import(User.class) // 先注释这个注解运行下面的结果
@Configuration // 声名配置类的注解
public class ImportTestDemo {
    public static void main(String[] args) {
        // 这个我们可以理解为spring通过注解方式发现并注册bean工厂的对象
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ImportTestDemo.class);
        // 所有对象名字集合
        String[] names = ac.getBeanDefinitionNames();
        for (String name : names) {
            // 打印看下bean工厂里面有那些对象
            System.out.println(name);
            System.out.println("----------------");
        }
    }

}

看下运行结果,只有我们声名的配置类打应出来了

importTestDemo
----------------

接下来我们用上import注解,并运行一下

@Import(User.class) // User是我自定义的一个实体
@Configuration // 声名配置类的注解
public class ImportTestDemo {
    public static void main(String[] args) {
        // 这个我们可以理解为spring通过注解方式发现并注册bean工厂的对象
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ImportTestDemo.class);
        // 所有对象名字集合
        String[] names = ac.getBeanDefinitionNames();
        for (String name : names) {
            // 打印看下bean工厂里面有那些对象
            System.out.println(name);
            System.out.println("----------------");
        }
    }

}

这个时候我们发现User对象也从spring容器中打印出来了,证明Impot注解有效果

importTestDemo
----------------
com.example.springbootredisson.bean.User
----------------

了解一下AutoConfigurationImportSelector的类,在第一个源码图中@Import中注解属性能看到
我们自己来实现一下ImportSelect

public class ImportSelectDemo implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        // 这里写死试试效果,当然spring有更优雅的代码检测出项目中的类
        return new String[]{Goods.class.getName(), User.class.getName()};
    }
}
@Configuration
@Import(ImportSelectDemo.class) // 自己实现的ImportSelect类
public class ImportTestDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ImportTestDemo.class);
        String[] names = ac.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
            System.out.println("----------------");
        }
    }

}
importTestDemo
----------------
com.example.springbootredisson.bean.Goods
----------------
com.example.springbootredisson.bean.User
----------------

到这里看到@Import和就是发现并注册类到spring容器中的作用
@EnableAutoConfiguration 注解作用就是将发现的类注册到ioc容器中,通过实现AutoConfigurationImportSelector这个类来发现并注册。下面再看来看importSelect这个类

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
                // 通过配置文件spring.factories发现类
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
                // 这里的返回值就是类对象的路径
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }

在往下看看getAutoConfigurationEntry(annotationMetadata)这个方法

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        // 获取spring.factories中的类路径 这里是springboot自动装配的主要方法
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = getConfigurationClassFilter().filter(configurations);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }

打开mybaties的starter看看是否有spring.factory配置文件


Snipaste_2021-02-24_23-18-18.png

结论:springboot读取spring.factories配置文件,读取配置文件加载类到ioc中,这就是第三方starter的原理,也就是springboot自动装配的原理。
因此我们在springboot中只需要引入第三方starter 就能开箱即用,同理我们可以自己打包一个starter给另外一个项目
使用如何自己写一个starter,这个很简单,em...百度一下就好了

上一篇下一篇

猜你喜欢

热点阅读