zoukankan      html  css  js  c++  java
  • 第二章 IOC + AOP 底层原理

    《精通Spring4.x 企业应用开发实战》读书笔记

    一、概念

    IOC:

    • 假设B类调用了A类,那么A类的对象的创建是由B类来实现;
    • IOC是指将A对象的创建由容器来完成,并且将创建好的对象注入到B类中供B类对象使用

    好处:

    • 减少对象的创建工作
    • 解耦B类与A类对象的创建过程

    二、Resource接口

    • “classpath:”:只会在第一个加载的com.xxx包的类路径下查找;
    • “classpath*:”:会扫描所有类路径下的com.xxx包中的查找

    三、Bean工厂

    • BeanFactory:
      • 容器启动时,将配置文件中的Bean装载到容器(hashMap<beanName, BeanDefinition>)
      • 配置文件中的Bean的初始化是在第一次调用时进行 - “懒实例化”
      • 缓存单例Bean,第二次调用时获取bean从IOC容器缓存中获取(hashMap<beanName, Bean>)
    • ApplicationContext:在BeanFactory的基础上,增加了“国际化支持”和“事件体系”
      • 事件体系:
        • ApplicationEventPublisher:发布事件,实际上会调用ApplicationEventMulticaster实例来发布。
        • ApplicationEventMulticaster:提供了监听器注册表,保存所有的监听器;发布事件,并通知相应的监听器进行相应操作
      • 上下文初始化时,创建所有单例Bean - “急切实例化”  

    四、Spring启动流程

    1、初始化BeanFactory

    • 创建BeanFactory实例
    • 将配置文件的信息装入BeanDefinitionRegistry(Bean定义注册表)中
      • 使用ResourceLoader将配置文件装载为Resource对象
      • 使用BeanDefinitionReader解析配置信息:将每一个<bean>解析为一个BeanDefinition对象,然后存储到BeanDefinitionRegistry中

    2、调用BeanFactoryPostProcessor

    • 根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanFactoryPostProcessor接口的Bean,并调用其postProcessBeanFactory()接口方法,实际上完成的工作主要是:- 可定制点
      • 对使用占位符的<bean>进行解析,得到最终的配置值,即将半成品的BeanDefinition转化为完全体的BeanDefinition对象
      • 根据反射机制从BeanDefinitionRegistry中找出所有实现了java.beans.PropertyEditor接口的Bean,并自动将他们注册到ProperEditorRegistry中

    3、注册BeanPostProcessor

    • 根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanPostProcessor接口的Bean,并将他们注册到BeanPostProcessor的注册表中 - 可定制点
    • 重要点:Aop、动态代理都是基于这个实现的

    4、初始化国际化信息资源

    5、初始化应用上下文事件广播器 - 事件

    6、初始化特殊的Bean:钩子方法 - 可定制点

    • springboot在这一步创建了TomcatEmbeddedServletContainer,即内嵌的tomcat容器

    7、注册事件监听器到ApplicationEventMulticaster的监听器注册表中

    8、初始化所有的单例Bean,使用懒加载的除外;初始化Bean后,放入spring容器的缓冲池(hashMap<beanName, Bean>

    • 取出BeanDefinitionRegistry中的BeanDefinition对象,使用InstantiationStrategy实例化Bean;
    • 使用BeanWrapper结合Bean实例和ProperEditorRegistry对Bean进行属性注入操作;
    • 使用3中注册好的BeanPostProcessor对已经完成属性设置的Bean进行后续加工,装配置出准备就绪的Bean。
    • 初始化 - init-method
    • 放入缓冲池(单例),多例交给调用者(后续该Bean的生命周期由垃圾回收来定了)

    9、发布上下文刷新事件 :创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中 - 事件

    类比:springboot启动核心流程

    1、创建SpringApplication对象

    • 判断是否是web环境
    • 创建并初始化ApplicationInitializer列表
    • 创建并初始化ApplicationListener列表
    • 初始化主类mainApplicationClass

    2、执行run方法

    • 获取SpringApplicationRunListeners
      • 创建了EventPublishingRunListener实例
      • 创建事件广播器SimpleApplicationEventMulticaster实例
      • 将之前初始化好的ApplicationListener列表全部注册到事件广播器的事件注册表中
    • 创建并初始化ConfigurableEnvironment
      • 创建一个MutablePropertySources复合属性源
      • 构造包含server.port等启动参数的属性源,并设置到复合属性源的首部,优先级最高
      • 读取application.properties文件内容,并构造为一个name为“applicationConfigurationProperties”的属性源,并设置到复合属性源的尾部
    • 创建ConfigurableApplicationContext
    • 准备ConfigurableApplicationContext
      • 执行初始化好了的ApplicationInitializer列表
    • 刷新ConfigurableApplicationContext
      • 将spring启动流程执行了一遍
    • 容器刷新后动作
    • SpringApplicationRunListeners发布finish事件

    五、BeanFactory中Bean生命周期

    大致来讲:

    • 创建Bean实例
    • 设置属性值以及对其他Bean的引用
    • 初始化 - init-method
    • 放入缓冲池(单例),多例交给调用者(后续该Bean的生命周期由垃圾回收来定了)
    • 销毁Bean - destroy - method

     六、AOP

    两种代理:

    • JDK:基于接口
      • 原理:动态代理 + 反射
      • 定义一个类XxHandler,实现InvocationHandler接口,里边包含真实对象的实例(实际上是一个Object,具体真实对象在运行期赋值给Object),并使用反射调用真实对象的指定方法
      • 使用Proxy.newProxyInstance(ClassLoader, interfaces, InvocationHandler)创建代理对象,之后调用相应的真实对象的方法即可。
        • 由于该方法的第二个对象是interface,所以JDK只能基于接口实现动态代理。
    • CGLib:基于类
      • 原理:动态生成字节码技术,即为将要拦截的类动态生成子类,然后在子类中拦截所有父类的调用并顺势织入横切逻辑。
      • 由于是创建子类,所以不能代理目标类中的private和final方法。

    比较:

    • CGLib创建代理对象花费的时间长于JDK,因为要动态生成子类
    • CGLib创建好的代理对象的性能由于JDK
  • 相关阅读:
    《经济学通识》六、生命有限
    《经济学通识》五、反垄断的罪与罚
    《经济学通识》四、贸易与互惠
    《经济学通识》三、价格与市场
    《经济学通识》二、管制的愿望与结果
    《经济学通识》一、前言
    《必然》十三、开始,正从脚下开始
    《必然》十二、一个好问题足以改变世界
    字符串之strstr
    STL之内存处理工具
  • 原文地址:https://www.cnblogs.com/java-zhao/p/7039868.html
Copyright © 2011-2022 走看看