spring boot自动装载的设计思想

一.反射机制

为什么要有反射机制这个东西

当我们使用new实例化对象时,时再jvm加载时就开始创建对象,分配内存空间,当我们将所有对象都使用new进行实例化时,再程序启动后,jvm加载完成,堆内存中就已经存在了大量的对象,占用了大量的内存空间,有些业务可能并不常用,导致有些对象也会并不常用,但是由于new的对象时强引用,gc并不会回收对象,导致大量内存被这些不常用对象占用,这个叫做静态编译。

如果将对象实例化的过程并不放在JVM加载过程中,二十再使用的时候才去申请内存空间,创建对象,就可以再jvm启动的时候,节省大量类的初始化时间和内存空间,这个叫做动态编译。

JAVA的反射机制就相当于将本应该JVM创建对象的过程,不再由JVM自己去处理,而是通过本地代码,在代码运行时手动通过经过编译的.class文件生成的class对象创建对象,当然由于反射的创建对象的过程不再由JVM执行,也就脱离了JVM创建对象时的一些审查和规范机制,比如通过反射破坏单例模式,对于详细的反射机制,包括反射如何破坏面向对象的封装性,会单独列一篇文章

二.spring IOC

spring ioc就大量使用了反射的思想,将所有BEAN的class对象路径储存,在需要使用的时候通过反射创建对象,由于创建对象的过程不再由JVM自动执行,而是由手动代码执行,所以也给了spring ioc极大的自由度,包括属性填充,方法填充等等。

从反射的基本原理到spring ioc都可以看出,动态编译的重点是需要class对象的路径。

三.自动装配

自动装配也是运用反射原理,在同一个程序中,我们可以通过xml文件,注解将信息记录到map中等形式去记录class对象路径,而当我们将另一个程序打包之后,该如何加载这个包的class信息?

可以规定一个约定

starter包就是约定实现的一部分,在starter包中,我们根据约定将需要装载的对象的class信息写道一个约定配置文件spring.factories中,当spring boot启动时,加载相应的starter包,会自动去寻找spring.factories配置文件,并遍历配置文件信息,加载配置文件中写好的class对象路径,然后放入ioc容器中,这就是spring boot自动装配的整体思想。

启动类上注解的作用
@SpringBootApplication
这个注解是springboot启动类上的一个注解,是一个组合注解,也就是由其他注解组合起来,它的主要作用就是标记说明这个类是springboot的主配置类,springboot应该运行这个类里面的main()方法来启动程序

在这里插入图片描述

 

这个注解主要由三个子注解组成:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

在这里插入图片描述

 

@SpringBootConfiguration
这个注解包含了@Configuration,@Configuration里面又包含了一个@Component注解,也就是说,这个注解标注在哪个类上,就表示当前这个类是一个配置类,而配置类也是spring容器中的组件

在这里插入图片描述

在这里插入图片描述 

@EnableAutoConfiguration
这个注解是开启自动配置的功能,里面包含了两个注解

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)

在这里插入图片描述 

@AutoConfigurationPackage
这个注解的作用说白了就是将主配置类(@SpringBootApplication标注的类)所在包以及子包里面的所有组件扫描并加载到spring的容器中,这也就是为什么我们在利用springboot进行开发的时候,无论是Controller还是Service的路径都是与主配置类同级或者次级的原因

在这里插入图片描述
@Import(AutoConfigurationImportSelector.class)
上一个注解我们把所有组件都加载到了容器里面,这个注解就是将需要自动装配的类以全类名的方式返回,那是怎么找到哪些是需要自动装配的类呢?

 

1、AutoConfigurationImportSelector这个类里面有一个方法selectImports(),如下在这里插入图片描述

 

2、在selectImport()方法里调用了一个getAutoConfigurationEntry()方法,这个方法里面又调用了一个getCandidateConfigurations()方法在这里插入图片描述

 

3、在getCandidateConfigurations()方法里面调用了loadFactoryNames()方法

在这里插入图片描述 

4、loadFactoryNames()方法里面又调用了一个loadSpringFactories()方法在这里插入图片描述

 

5、关键就在这个loadSpringFactories()方法里面,在这个方法里,它会查找所有在META-INF路径下的spring.factories文件

在这里插入图片描述

在这里插入图片描述
6、在META-INF/spring.factories这个文件里面的数据是以键=值的方式存储,然后解析这些文件,找出以EnableAutoConfiguration为键的所有值,以列表的方式返回

 在这里插入图片描述

在这里插入图片描述

 

@ComponentScan
这个注解的作用就是扫描当前包及子包的注解

2.2、springboot自动装配的流程
1、在springboot启动的时候会创建一个SpringApplication对象,在对象的构造方法里面会进行一些参数的初始化工作,最主要的是判断当前应用程序的类型以及设置初始化器以及监听器,并在这个过程中会加载整个应用程序的spring.factories文件,将文件中的内容放到缓存当中,方便后续获取;

2、SpringApplication对象创建完成之后会执行run()方法来完成整个应用程序的启动,启动的过程中有两个最主要的方法prepareContext()和refreshContext(),在这两个方法中完成了自动装配的核心功能,在run()方法里还执行了一些包括上下文对象的创建,打印banner图,异常报告期的准备等各个准备工作,方便后续进行调用;

3、在prepareContext()中主要完成的是对上下文对象的初始化操作,包括属性的设置,比如设置环境变量。在整个过程中有一个load()方法,它主要是完成一件事,那就是将启动类作为一个beanDefinition注册到registry,方便后续在进行BeanFactoryPostProcessor调用执行的时候,可以找到对应执行的主类,来完成对@SpringBootApplication、@EnableAutoConfiguration等注解的解析工作;

4、在refreshContext()方法中会进行整个容器的刷新过程,会调用spring中的refresh()方法,refresh()方法中有13个非常关键的方法,来完成整个应用程序的启动。而在自动装配过程中,会调用的关键的一个方法就是invokeBeanFactoryPostProcessors()方法,在这个方法中主要是对ConfigurationClassPostProcessor类的处理,这个类是BFPP(BeanFactoryPostProcessor)的子类,因为实现了BDRPP(BeanDefinitionRegistryPostProcessor)接口,在调用的时候会先调用BDRPP中的postProcessBeanDefinitionRegistry()方法,然后再调用BFPP中的postProcessBeanFactory()方法,在执行postProcessBeanDefinitionRegistry()方法的时候会解析处理各种的注解,包含@PropertySource、@ComponentScan、@Bean、@Import等注解,最主要的是对@Import注解的解析;

5、在解析@Import注解的时候,会有一个getImport()方法,从主类开始递归解析注解,把所有包含@Import的注解都解析到,然后在processImport()方法中对import的类进行分类,例如AutoConfigurationImportSelect归属于ImportSelect的子类,在后续的过程中会调用DeferredImportSelectorHandler类里面的process方法,来完成整个EnableAutoConfiguration的加载。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

伤何123

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值