Spring底层核心原理理解

46 阅读4分钟

1.bean的创建过程:

  • 主要过程:UserService-->构造方法(推断构造方法)-->对象(里面的OrderService属性没有值)-->依赖注入(属性赋值)-->初始化前(@PostConstruct)-->初始化(实现InitializingBean)-->初始化后(AOP->代理对象)-->Bean
  • 对象 instance of InitializingBean 判断是否实现该类
  • 构造方法的参数对象查找:spring查找容器bean先通过对象类型查找,如果有多个,再根据名字查找
  • UserServiceProxy(cglib)--->代理对象--->代理对象.target=普通对象
  • 代理对象.test();
class UserServiceProxy extends UserService{
      UserService target;
      public void test(){
        //执行切面@Before (缓存map获取方法)
        target.test();
   }
}
  • 判断是否要进行AOP代理对象创建:
  1. 找出所有的切面Bean
  2. 遍历
  3. 遍历方法
  4. 方法===》UserService 缓存map
  • 判断是否创建事务代理对象:
  1. 事务@transactional
  2. 创建一个数据库连接conn(事务管理器dataSource)
  3. conn.autocommit=false
  4. 执行原方法sql
  5. conn.commit();
  6. conn.rollback();
  • 方法调用事务失效:看调用对象是否是代理对象,是的话就不会失效
  • 不加@Configuration注解事务会失效:加注解是保证只有一个dataSource,执行原方法sql和事务管理器dataSource是一个。 AppConfig代理对象去容器里面拿dataSource

2.手写模拟Spring底层原理

1.Spring的底层源码启动过程
  1. @Scope("prototype") 原型=多例
  2. 创建applicationContext对象,根据入参配置类的配置的扫描地址扫描包路径
  3. 通过扫描class类判断是否有@component注解
  4. 如果有注解就创建BeanDefinition对象存储到BeanDefinitionMap里面
  5. 根据BeanDefinition创建单例bean存储在singletonMap里面
  6. getBean的时候如果是原型bean创建原型bean并返回,如果是单例bean从singletonMap里面获取bean并返回
  7. 依赖注入
  8. 初始化->实现InitializingBean接口
  9. 初始化前后->实现BeanPostProcessor接口
2.BeanDefinition,BeanPostProcessor的作用
  • BeanDefinition:type,scope,isLazy
  • BeanPostProcessor:初始化后可以创建AOP的动态代理对象,初始化前可以自定义注解实现自己的功能
  • 定义bean:@Bean @component
  • Map<String,BeanDefinition>
  • Map<String,Object>
  • List<BeanPostProcessor>
3.Aware回调的应用

BeanNameAware回调,BeanFactoryAware回调 在初始化之前执行

3.依赖注入解决方案

Aservice出现了循环依赖的情况下,才需要提前进行AOP

  • 先创建AService,执行AService的生命周期
  1. creatingSet
  2. 实例化AService-->得到一个对象-->singletonFactories<AService:lambda<AService原始对象>>
  3. 填充BService属性-->去单例池中找BService-->singletonObjects--->没有则创建BService
  4. 填充cService属性
  5. 初始化前、初始化
  6. 初始化后-->AService代理对象
  7. 放入单例池
  • 创建BService,执行BService的生命周期
  1. 实例化BService-->得到一个对象-->singletonFactories<BService :lambda< Bservice原始对象>>
  2. 填充AService属性->去单例池中找aervice-->creatingset->出现了循环依赖-->eanrlysingletonobjects->singletonfactories->Lambda->执行->earlysingletonobiect
  3. 填充其他属性
  4. 初始化前、初始化
  5. 初始化后
  6. 放入单例池
  • 创建cService,执行BService的生命周期
  1. 实例化BService-->得到一个对象-->singletonFactories<CService : lambda<CService原始对象>>
  2. 填充AService属性-->去单例池中找AService-->creatingSet-->出现了循环依赖-->earlySingletonobjects
  3. 填充其他属性
  4. 初始化前、初始化
  5. 初始化后
  6. 放入单例池
  • 三级缓存的作用:
  1. singletonObjects:缓存经过了完整生命周期的bean
  2. earlysingletonObjects:缓存未经过完整生命周期的bean,如果某个bean出现了循环依赖,就会提前把这暂时未经过完整生命周期的bean放入earlySingletonObjects中,这个bean如果要经过AOP,那么就会把代理对象放入earlySingletonObiects中,否则就是把原始对象放入earlyingletonObjects,但是不管怎么样,就是是代理对象,代理对象所代理的原始对象也是没有经过完整生命周期的,所以放earlySingletonObjects我们就可以统一认为是未经过完整生命周期的bean
  3. singletonFactories:缓存的是一个0bjectFactory,也就是一个Lambda表达式。在每个Bean的生成过程中,经过实例化得到一个原始对象后,都会提前基于原始对象暴露一个Lambda表达式,并保存到三级缓存中,这个Lambda表达式可能用到,也可能用不到,如果当前Bean没有出现循环依赖,那么这个Lambda表达式没用,当前bean按照自己的生命周期正常执行,执行完后直接把当前bean放入singletonObjects中,如果当前bean在依赖注入时发现出现了循环依赖(当前正在创建的bean被其他bean依赖了),则从三级缓存中拿到Lambda表达式,并执行Lambda表达式得到一个对象,并把得到的对象放入二级缓存((如果当前Bean需要AOP,那么执行lambda表达式,得到就是对应的代理对象,如果无需AOP,则直接得到一个原始对象))。
  4. 其实还要一个缓存,就是earlyProxyReferences,它用来记录某个原始对象是否进行过AOP了。