框架的简单源码流程分析

366 阅读4分钟

MyBatis

MyBatis 执行流程

  1. SqlSessionFactory获取SqlSession
    1. TransactionFactory新建Transaction
    2. 根据Transaction和ExecutorType(Simple,Reuse,Batch)通过Configuration获取Executor(中间InteceptorChain适配插件)
    3. 参数Configuration,Executor和Autocommit创建DefaultSqlSession
  2. Select(statement,param,RowBounds,ResultHandler)
    1. 根据statement获取MapperStatement
    2. 根据不同的Executor(BaseExecutor,CacheExecutor)调用query()
      1. MapperStatement根据param获取BoundSql(封装参数和sql)
      2. 创建CacheKey
      3. 从一级缓存中获取(BaseExecutor)
      4. 如果一级缓存中获取不到,则创建StatementHandler(中间InteceptorChain适配插件)
      5. 对Statement进行预处理(设置超时,参数等)
      6. Statement执行sql
      7. ResultSetHandler对结果进行封装

MyBatis为什么@Autowired即可注入实现类

  1. MapperScannerConfigurer实现 BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()
  2. Spring默认注入MapperFactoryBean 代码(definition.setBeanClass(this.mapperFactoryBean.getClass()))
  3. MapperFactoryByean.getObject()
    1. getSqlSession().getMapper(this.mapperInterface);
  4. DefaultSession.getMapper()
  5. 通过Configuration获取Mapper(Class, DefaultSession)
    1. 通过Configuration的MapperRegistry.getMapper(Class, DefaultSession()
    2. 通过Configuration的MapperRegistry.getMapper(Class, DefaultSession)
    3. 根据Class获取MapperProxyFactory
    4. MapperProxyFactory.newInstance()
    5. 根据SqlSesison,MapperInterface创建MapperProxy
    6. Proxy.newProxyInstance()

Spring

启动流程

  1. prepareRefresh() - 准备此上下文以进行刷新,设置其启动日期和活动标志以及执行属性源的任何初始化。
  2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() - 告诉子类刷新内部bean工厂。
    1. 如果存在beanFactory则销毁。
    2. 创建beanFastory(DefaultListableBeanFactory),并且装在配置文件
  3. prepareBeanFactory(beanFactory) - 准备bean工厂以在此上下文中使用(预处理 例:设置类加载器,设置忽略等)。
  4. postProcessBeanFactory(beanFactory) - 允许在上下文子类中对bean工厂进行后处理。(例如Mybatis的Confituration通过实现该方法,自定义实现注入MapperFactoryBean,后续获取Mapper实现类在通过MapperFactoryBean来获取)
  5. invokeBeanFactoryPostProcessors(beanFactory) - 在上下文中调用注册为beanFactory的后置处理器。
    1. 获取实现PriorityOrdered的BeanDefinitionRegistryPostProcessor,排序并调用
    2. 获取实现Ordered的BeanDefinitionRegistryPostProcessor,排序并调用
    3. 调用其他的BeanDefinitionRegistryPostProcessor
  6. registerBeanPostProcessors(beanFactory) - 注册拦截bean创建的bean处理器。
    1. 获取实现PriorityOrdered的BeanPostProcessors,排序并调用
    2. 获取实现Ordered的BeanPostProcessors,排序并调用
    3. 调用其他的BeanPostProcessors
  7. initMessageSource() - 初始化国际化相关
  8. initApplicationEventMulticaster() - 初始化事件广播器(观察者模式)
  9. onRefresh() - 在特定的上下文子类中初始化其他特殊bean(空实现,有需要子类来实现)。(模板方法模式,此方法又称钩子方法)
  10. registerListeners() - 注册监听器(在事件广播器中注册)
  11. finishBeanFactoryInitialization(beanFactory) - 完成工厂初始化(实例化所有剩余的[非延迟初始化]单例 注:默认都为懒加载)。
  12. finishRefresh() - 完成容器初始化(发布上下文刷新事件)

循环依赖解决

入口: AbstractBeanFactory#doGetBean

Spring 注入对象分为三个步骤

  1. createBeanInstance: 实例化(构造器)
  2. populateBean: 填充属性(设置字段)
  3. initializeBean: init 方法

Sring 解决循环依赖依靠三级缓存

/** 
* Cache of singleton objects: bean name –> bean instance 
* 完成初始化的单例对象的cache (一级缓存)
*/
private final Map singletonObjects = new ConcurrentHashMap(256);

/** 
* Cache of early singleton objects: bean name –> bean instance 
* 完成实例化但是尚未初始化的,提前暴光的单例对象的Cache (二级缓存)
*/
private final Map earlySingletonObjects = new HashMap(16);

/** 
* Cache of singleton factories: bean name –> ObjectFactory 
* 进入实例化阶段的单例对象工厂的cache (三级缓存)
*/
private final Map> singletonFactories = new HashMap>(16);
  1. 调用父类 DefaultSingletonBeanRegistry#getSingleton(String beanName, boolean allowEarlyReference)
    1. 如果一级缓存中有, 则说明已经初始化, 直接使用
    2. 如果一级缓存中没有, 但是正在创建.
    3. 如果二级缓存中没有, 则手动创建并且将对象放入二级缓存, 并将三级缓存中的实例对象清除
    4. 如果二级缓存有, 则使用
    5. 如果没有, 则返回 null
  2. 如果没有获取到对象, 则说明需要实例化该对象 DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory)
    1. 第一步, 预先将该对象名称放入singletonsCurrentlyInCreation, 表示正在创建
    2. 实例化该对象
    3. 设置该对象属性
    4. 执行 init
    5. 放入一级缓存并从二级缓存中清除

Feign

  1. 自动配置入口: FeignClientsRegistrar#registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry)
    1. 注入 feign 类: FeignClientsRegistrar#registerFeignClient
private void registerFeignClient(BeanDefinitionRegistry registry,
    AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
    String className = annotationMetadata.getClassName();
    BeanDefinitionBuilder definition = BeanDefinitionBuilder
    .genericBeanDefinition(FeignClientFactoryBean.class);
    validate(attributes);
    definition.addPropertyValue("url", getUrl(attributes)); 
    definition.addPropertyValue("path", getPath(attributes));
    String name = getName(attributes);
    definition.addPropertyValue("name", name);
    definition.addPropertyValue("type", className);
    definition.addPropertyValue("decode404", attributes.get("decode404"));
    definition.addPropertyValue("fallback", attributes.get("fallback"));
    definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
    definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);

    ...
    BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
  1. 自动配置类: FeignAutoConfiguration (默认使用 URLConnection, 可选择 ApacheHttpClient 还是 OkHttpClient )
  2. FactoryBean.getObject() -> FeignClientFactoryBean.getObject()
  3. 设置属性: FeignClientFactoryBean#feign()
    1. Encoder
    2. Dncoder
    3. Contact (SpringMvcContract 通过继承BaseContract, 默认注册AnnotatedParameterProcessor的子类来实现支持 Spring 注解. 即RequestHeader, RequestParam, PathVariable等注解)
  4. 拼接 URL, 负载均衡
  5. feign.Feign.Builder#target(feign.Target)
    1. build(): 设置客户端, 重试, 拦截器, encoder, decoder
    2. instance(): 构造动态代理 (SynchronousMethodHandler)
  6. 动态代理执行: SynchronousMethodHandler#invoke
    1. 根据 metadata 创建RequestTemplate(设置urlIndex, bodyIndex, headerMapIndex, queryMapIndex等)
    2. 解析 encode(ReflectiveFeign.BuildTemplateByResolvingArgs#resolve)
    3. 使用原型模式克隆 Retryer
    4. 执行和解析: SynchronousMethodHandler#executeAndDecode
      1. 执行拦截器: feign.SynchronousMethodHandler#targetRequest
      2. 执行请求: client.execute(request, options)
      3. 根据不同的状态码解析结果
    5. 如果需要重试则重试, 返回结果

线程池

原理

  1. 判断是否超过核心线程if (workerCountOf(c) < corePoolSize)

    1.1 没有超过则新建线程addWorker(command, true)

    1.2 如果超过则执行第二步

  2. 尝试往工作队列里放入if (isRunning(c) && workQueue.offer(command))

    1.1 放入成功则退出

    1.2 放入失败则执行第三步

  3. 新建线程(但是小于最大线程)