SpringBoot自动装配原理

日期:2022年8月23日

在这里插入图片描述
我们可以按住Shift+鼠标右键,进入查看@SpringBootApplication
在这里插入图片描述
其中:
@Target({ElementType.TYPE}) (用来规定下面这个注解的使用位置)表明这个注解要加到类上。

@Retention(RetentionPolicy.RUNTIME)(用来规定下面这个注解的存活时间)表明可以存活在运行时。

@Inherited:表明这个类的子类也可以继承该注解

@Documented :( 具体效果演示)是 java 在生成文档,是否显示注解的开关

//核心注解
@SpringBootConfiguration :表明当前类是一个SpirngBoot配置类
@EnableAutoConfiguration:表明该类支持自动装配

@ComponentScan:需要扫描的包(但这里看不出来都扫描哪个包,往下看)
在这里插入图片描述
查看@EnableAutoConfiguration

点开@EnableAutoConfiguration注解如下:
在这里插入图片描述
@AutoConfigurationPackage:指定需要扫描配置的包,就是springboot启动类所在的包。

@Import({AutoConfigurationImportSelector.class}):导入AutoConfigurationImportSelector这个配置类.加载自动配置的类。

查看@AutoConfigurationPackage
在这里插入图片描述
里面会有一个@Import({Registrar.class}) 它的作用是导入 Registrar这个类
在这里插入图片描述
我们可以debug,看一下这个类的作用
在这里插入图片描述
如图我们可以看到这个类的一个作用是查看当前项目的启动类所处的包。

查看@Import({AutoConfigurationImportSelector.class})
我们进入AutoConfigurationImportSelector类:
在这里插入图片描述
其中这个类实现了DeferredImportSelector类,
在这里插入图片描述
并且DeferredImportSelector也实现了ImportSelector
在这里插入图片描述
那在ImportSelector这个类有一个方法,

String[] selectImports(AnnotationMetadata var1);

这个方法的的作用是将此方法的返回值都加载到spring容器中。

//例子
//我们新建一个Person类
public class person {
    private String name;
    private int age;
}
//在新建一个类实现ImportSelector
public class MySpringbootTest implements ImportSelector {
//重写selectImports
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.example.test.person"};//Person的全限定名
    }
}
//在启动类中加入@Import()
@SpringBootApplication
@Import(MySpringbootTest.class)
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
//测试
@SpringBootTest
public class ImportTest {

    @Autowired
    private person p;

    @Test
    public void test1(){
        System.out.println(p);
    }
}

在这里插入图片描述
可以看到我这里没有加任何包扫描注解,但是确能实例化Person。

我们回到AutoConfigurationImportSelector类,在这个类中有一个核心方法getAutoConfigurationEntry:
在这里插入图片描述
在这个方法中调用了getCandidateConfigurations(annotationMetadata, attributes)方法,这个方法的作用是把类作为key:org.springframework.boot.autoconfigure.EnableAutoConfiguration
在这里插入图片描述

在这里插入图片描述
加载META-INF/spring.factories中所有的key对应的value值。
在这里插入图片描述
我们可以按两下 shift 查看一下spring.factories
在这里插入图片描述
点进去就可以看到:
在这里插入图片描述
回到 class AutoConfigurationImportSelector ,他就可以接收到这些配置信息
在这里插入图片描述

那么再回到@interface SpringBootApplication
在这里插入图片描述
我们点击@ComponentScan的AutoConfigurationExcludeFilter.class
在这里插入图片描述
看到这里我们就可以知道了,@ComponentScan都扫描了哪些包

总结流程:

我们进入@SprignbootApplication这个注解中,里面会有四类注解
其中:
1.元注解包括@Target(声明当前注解的使用位置),@Retention(声明这个注解的生命周期)
@Document(用来显示在doc在显示注解信息),@Inherited(用来标记子类是否继承该注解)。

2.@SpringBootConfiguration(用来标记这是一个springboot配置类)。
3.@EnableAutoConfiguration(核心注解,用来实现springboot自动装配)
4.@ComponentScan(包扫描),这个注解大家都熟悉,但是我们可以看到它并没有明确写出他需要扫面哪些包,但是在括号里面我们可以看到,有两个@filter ,其中在第二filter中,他会加载AutoConfiguration.class这个类,那在这个类中,有一个getAutoConfiguration方法,他会通过Spring工厂加载去加载@interface EnableAutoConfiguration,这个注解,那在@EnableAutoConfiguration中,有三类注解:
A:元注解(自己去看)
B:@AutoConfigurationPackage,在这个注解里面也有一个注解@Import, 这个注解是为将符合条件的bean加载到Ioc容器中,那这里是引入的Registrar.class这个类,在这个类中有一个方法:getRegistrarBeanDefinition(AnnotationMetadata metadata, BeanDefinitionRegistry registry),那这个方法的作用其实就是得到当前启动类的包路径。
C:@Import(AutoConfigurtionImportSelector.class),这个注解是为了加载AutoConfigurtionImportSelector这个类,那在这个类中有三个核心方法,其中:

  • a:通过重写ImportSelector接口中的方法selectImports,这个方法的作用是为了将需要的类,加载到Spring容其中。
  • b:getCandidateConfiguration(AnnotationMetadata metadata, AnnotationAttributes attributes),这个方法的作用通过SpringFactoriesLoader去加载,以key=value的方式去读取在每个jar包中META-INF/spring.factories 中Sprongboot帮我们配置好的配置类路径。
  • c:然后在getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata)中去调用b的方法,对得到的list进行包括去重、检查是否有排除的等操作后赋值给 configurations 集合。然后将参数传给AutoConfigurationEntry这个类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皇家小黄

创作不易!!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值