基本概念

启动原理

参考 https://www.cnblogs.com/theRhyme/p/11057233.html#_label1
https://www.jianshu.com/p/87f101d8ec41

1:ioc/DI

参考:https://blog.csdn.net/ivan820819/article/details/79744797
一种编程思想,引入容器管理对象,使得对象之间解耦
实现原理参考 https://blog.csdn.net/vannesspeng/article/details/79486922

2:aop

参考:https://www.cnblogs.com/joy99/p/10941543.html
面向切面编程,一种编程思想。(类似python的装饰器)可以自定义作用范围
基本使用demo
导入依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>
  1. @Aspect
  2. @Component
  3. public class AcceptUtil {
  4. @Pointcut("execution(public * com.example..*.*(..))") //定义切入点
  5. public void acceptUtil(){}
  6. @After("acceptUtil()")
  7. public void after(JoinPoint joinPoint){
  8. System.out.println("执行 after");
  9. }
  10. @Before("acceptUtil()")
  11. public void before(JoinPoint joinPoint){
  12. System.out.println("执行 before");
  13. }
  14. @Around("acceptUtil()")
  15. public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
  16. System.out.println("=====前");
  17. Object proceed = joinPoint.proceed();
  18. System.out.println("=====后");
  19. return proceed;
  20. }
  21. }

自定义注解

  1. @Target({ElementType.METHOD,ElementType.TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface CusomAop { }
  4. //注解实现
  5. @Aspect
  6. @Component
  7. public class CusomAopImpl {
  8. @Around("@annotation(CusomAop)")
  9. public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
  10. System.out.println("执行开始时间"+new Date());
  11. Object proceed = joinPoint.proceed();
  12. System.out.println("执行结束时间"+new Date());
  13. return proceed;
  14. }
  15. }

自动配置

源码解读

1:从0开始

image.png

2: new SpringApplication

image.png3

2.1 deduceFromClasspath 猜一下环境类型? 默认的就是 SERVLET

image.png

3: getSpringFactoriesInstances

这个方法后面经常会用到
image.png

4:重点看 SpringFactoriesLoader.loadFactoryNames

这个方法是从 spring.factories 中读取配置信息,然后获取指定的 _factoryType 内容
_spring.factories 长这样,,key:value形式,_factoryType 就是key
image.png
image.png

5:loadSpringFactories 干活的,根据类加载器读取配置文件

image.png

image.png
image.png

=====第一部分结束。此时已经拿到了 spring.factories 中所有的配置信息
_cache 结构 { classLoad :{factories : [ ……] ,….} }

image.png

6:run方法

image.png
7:环境 prepareEnvironment
image.png
image.png
返回一个 SERVLET 环境 ==直译就是标准的SERVLET 环境 。。。

_7:_createApplicationContext 创建容器

image.png

所以这里返回的就是 AnnotationConfigServletWebServerApplicationContext

8:这个类关系挺乱。。先上图

image.png

9: 接下来是重点refreshContext

一直委托到 父类 ,在 AbstractApplicationContext 上面的图中能找到
image.png

_10.先搞清楚一个重要概念 _beanFactory ,后面会不断的出现

obtainFreshBeanFactory 看这个方法
顾名思义,这是一个bean工厂
他是哪来的?
还得从 _7:_createApplicationContext 创建容器 说起 根据 7.1 的图,AnnotationConfigServletWebServerApplicationContext 实例化时
image.png 调用父类
ServletWebServerApplicationContext 无参
image.png
再调用 父类 GenericWebApplicationContext 无参
image.png
最终到
image.png

这是默认的beanFactory DefaultListableBeanFactory

10.1 DefaultListableBeanFactory 关系图

image.png

10.2:prepareBeanFactory 对beanFactory 一顿设置,不知道干啥,有空看?

image.png

12:invokeBeanFactoryPostProcessors

重点看这个
image.png

12.1 里面的 参数 getBeanFactoryPostProcessors()

image.png
两个参数是在 2 中初始化的 都实现了 ApplicationContextInitializer接口
image.png
image.png
image.png

13:对上面两个参数分类,放到列表中,并调用他们的 postProcessBeanDefinitionRegistry 方法

image.png

13.1 分别看一下两个的 postProcessBeanDefinitionRegistry 方法

13.1.1:CachingMetadataReaderFactoryPostProcessor

两个操作
1:注册bean,
生成bean 并放到 beanDefinitionMap和 beanDefinitionNames 中
image.png
beanDefinitionMap 名称更实例的map
image.png
beanDefinitionNames 这里放置bean名称
image.png

13.1.2 configureConfigurationClassPostProcessor 方法

image.png
没看明白这个,好像是拿bean的回调方法,如果没有,给他配置一个默认的

14 :拿到实现 BeanDefinitionRegistryPostProcessor 接口的bean列表
这两块代码重复了?都是拿到以后调用 postProcessBeanDefinitionRegistry 方法
image.png
15: ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry
这个用于扫描所有注解,比如contorller comport
类图
image.png
16:委托到 processConfigBeanDefinitions方法
image.png
看 checkConfigurationClassCandidate
拿到包含 Configuration 注解的方法
image.png

中间一顿操作。。。。
这里定义了一个配置解析器,用于解析注解
image.png

17:parse 方法
image.png
委托到 processConfigurationClass方法

image.png
18:doProcessConfigurationClass 真正干活的
一顿操作拿到当前解析类下所有 注解
image.png
拿到后 调用parse方法调用 processConfigurationClass 放到 configurationClasses 中
image.png
处理其他注解,这里就跟上面重复了
image.png

image.png
如果没有指定读取器,给一个默认的

image.png
拿到所有bean名称,
image.png

====第二部分结束,当前所有默认配置及自定义配置bean都已经扫描
并且处理好了接口方法

image.png
开始扫描根目录
image.png