SpringBoot 自动装配原理

1、预备知识

1.1 @Import注解和ImportSelector接口

通过@Import注解和配置类实现了ImportSelector接口,可以实现被@Import注解修饰的类导入覆写了ImportSelector接口中selectImports()方法返回的类的全路径名称。

下面举个例子:

package com.jerry.springbootstudy.demo;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @Description: ImportSelector-demo
 * @Author: Jerry
 * @Date: 2021-05-13 22:55
 */
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[] {
                User.class.getName(),
                Role.class.getName()
        };
    }
}

该类实现了ImportSelector接口,并复写了selectImports方法,该方法返回要自动装配到Spring容器中的类名称。这里的demo中,返回我们自己定义个User类和Role类的类名。

User:

package com.jerry.springbootstudy.demo;

/**
 * @Description: User类
 * @Author: Jerry
 * @Date: 2021-05-13 22:56
 */
public class User {
}

Role:

package com.jerry.springbootstudy.demo;

/**
 * @Description: 角色二类
 * @Author: Jerry
 * @Date: 2021-05-13 22:56
 */
public class Role {
}

Config配置类:

package com.jerry.springbootstudy.demo;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * @Description: 配置类
 * @Author: Jerry
 * @Date: 2021-05-13 22:58
 */
@Configuration
@Import(MyImportSelector.class)
public class Config {
}

说明:

  • 通过@Import注解引入我们上面ImportSelector接口的实现类,将selectImports方法中返回的类名对应的bean装配到Spring容器中;
  • 通过@Configuration注解将config类自身装配到Spring容器中。

测试类:

package com.jerry.springbootstudy.demo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Arrays;

public class ConfigTest {
    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        String[] names = context.getBeanDefinitionNames();
        Arrays.stream(names).forEach(System.out::println);
    }
}

测试类中获取context容器,从容器中获取自动装配到容器中的bean名称并打印,结果如下:

结果可以看出,我们通过ImportSelector接口的实现类的selectImports方法返回的类的bean,成功装配到Spring容器中。

1.2 spring.factories中的EnableAutoConfiguration配置

在很多Spring相关的依赖的META-INF目录下都能看到spring.factories文件,比如在spring-boot-autoconfigure依赖的META-INF目录下就能看到这个文件,如图:

在该文件中的EnableAutoConfiguration配置下,就存放有该依赖中要加载到Spring容器中的bean,还是以spring-boot-autoconfigure的spring.factories为例,如下:

我们看到有rabbitmq相关的配置类,在spring-boot-autoconfigure依赖下果然能找到RabbitAutoConfiguration类,如下:

2、相关源码分析

整体流程如下图所示:

说明:

  • 通过在@EnableAutoConfiguration注解里用@Import(EnableAutoConfigurationImportSelector)注解的方式将自动装配的类加载到Spring容器中,哪些类需要加载是由AutoConfigurationImportSelector类里实现额selectImports方法返回;
  • 在selectImports方法中,最重要的方法是getCandidateConfigurations方法,该方法里主要是loadFactoryNames方法,该方法读取依赖中META-INF目录下的spring.factories文件,获取spring.factories文件中EnableAutoConfiguration配置下所有要自动装配的类的名称并返回。

3、面试说辞

  • 在SpringBoot的启动类上有一个@SpringBootApplication注解,这个注解里有一个@EnableAutoConfiguration注解;
  • @EnableAutoConfiguration注解通过@Import导入了一个EnableAutoConfigurationImportSelector类,该类实现了ImportSelector接口,实现了selectImports方法,该方法会返回需要自动装配到Spring容器中的类的名称;
  • 再看selectImports方法,该方法只要有三步:
    1. getCandidateConfigurations方法获取所有的bean;
    2. 获取@SpringBootApplication注解中execlude指定的不需要自动装配的类;
    3. 返回a中去掉b中的类。
  • 主要看getCandidateConfigurations方法,该方法里有一个loadFactoryNames方法,这个方法读取依赖中META-INF目录下的spring.factories文件,获取spring.factories文件中EnableAutoConfiguration配置下所有要自动装配的类的名称并返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值