文章目录
学习到SpringBoot,有必要更进一步理解和学习Spring更深层的东西。这就学习和整理了这一篇文章。
参看:
- 《深入理解JVM虚拟机》第三版
- https://spring.io
- https://mp.weixin.qq.com/s/WpRSitDqtgOuU9GnI1-HDw
- https://blog.csdn.net/xiaofeng10330111/article/details/105631666
- https://mp.weixin.qq.com/s/NXZp8a3n-ssnC6Y1Hy9lzw
- https://cloud.tencent.com/developer/article/1584491
中文版官方文档分享
https://www.jianshu.com/p/b3da0c8a22fe
一、Spring IOC
DI和IOC
Bean是包装的Object,无论是控制反转还是依赖注入,它们的主语都是object。Bean是Spring的主角。
Dependency Injection,依赖注入:容器动态的将某个依赖关系注入到组件之中。通过简单的配置,无需任何代码就可指定目标需要的资源,无需关心资源来自何处。**且被注入对象依赖IOC容器配置依赖对象。**可以说DI是IOC设计思想的实现。
Inversion of Control,控制反转。控制反转就是把创建和管理 bean 的过程转移给Spring IoC Container,对于 IoC 来说,最重要的就是容器。容器管理着 bean 的生命,控制着 bean 的依赖注入。
有了ioc容器,我们每次需要使用对象的时候,直接从容器中取出、使用即可,不用去关心如何创建、销毁等。
DI和IOC的关系
同一个概念的不同描述,IOC是一种设计思想,DI是一种实现。DI是IOC思想的实现,即容器管理Bean使用依赖注入技术实现。
当IOC容器实现了Bean的资源定位、载入和解析注册后,会对所管理的Bean进行依赖注入,发生依赖注入的情况:
- 第一次调用BeanFactory的getBean()方法时,ioc容器触发依赖注入。
- 关闭lazy-init懒加载时,容器在解析注册bean的时候会继续预实例化,触发依赖注入。
IOC容器初始化
分为四步:资源定位、载入、解析注册和依赖注入。
IOC容器初始化的两个基本步骤:
- 初始化的入口由 容器中的refresh()方法 调用完成。
- 对Bean定义载入IOC容器使用的方法是 loadBeanDefinition()。
大致过程:
- 通过ReasourceLoader来完成资源文件的定位,DefaultResourceLoader是默认的实现,同时上下文本身就给出了ResourceLoader的实现,可以通过类路径、文件系统、URL等方式来定位资源。
- 如果XmlBeanFactory作为IOC容器,那么需要为它指定Bean定义的资源,也就是说Bean定义文件是通过抽象成Resource来被IOC容器处理,容器通过BeanDefinitionReader来完成定义信息的解析和Bean信息的注册,往往使用XmlBeanDefinitionReader来解析Bean的XML定义文件—实际的处理过程是委托给BeanDefinitionParserDelegate来完成的,从而得到Bean的定义信息,这些信息在Spring中使用BeanDefinition来表示(这个名字可以让我们想到loadBeanDefinition()、registerBeanDefinition()这些相关的方法,他们都是为处理BeanDefinition服务的)。
- 解析得到BeanDefinition以后,需要在IOC容器中注册,这由IOC实现BeanDefinitionRegister接口来实现,注册过程就是在IOC容器内容维护一个HashMap来保存得到的BeanDefinition的过程,这个HashMap是IOC容器持有Bean信息的场所,以后Bean的操作都是围绕这个HashMap来实现。
- 之后我们通过BeanFactory和ApplicationContext来享受Spring IOC的服务了,在使用IOC容器的时候我们注意到,除了少量粘合代码,绝大多数以正确IOC风格编写的应用程序代码完全不关心如何到达工厂,因为容器将把这些对象与容器管理的其他对象钩在了一起,基本的策略是把工厂放到已知的地方,最好放在对预期使用的上下文有意义的地方,以及代码要实际访问工厂的地方。
- Spring本身提供了对声明式载入Web应用程序用法的应用程序上下文,并将其存储在ServletContext的框架实现中。
二、Spring AOP
aspect oriented programming,面向切面编程。在不修改源代码的前提下,通过 预编译+运行时动态代理 实现在不同的业务组件添加某些通用功能。
它与 OOP( Object-Oriented Programming, 面向对象编程) 相辅相成, 提供了与 OOP 不同的抽象软件结构的视角。在 OOP 中, 我们以类(class)作为我们的基本单元, 而 AOP 中的基本单元是 Aspect(切面)。
实际上可以应用AOP的业务场景很多,如权限验证、会话管理和操作日志记录等,这些都可以通过AOP进行增强。
1.名词解释
JoinPoint(连接点)
程序在执行过程中,一个个的时间点,比如调用时、抛出异常时等,这些时间点可以注入切面代码(可选)。
Pointcut(切点)
JoinPoint表示切面代码可以被织入的地方,根据需求切入到某些点,就需要用到 Pointcut
定义规则匹配JoinPoint(Aspect Pointcut expression language 描述规则)。
Advice(增强)
在Pointcut匹配到JoinPoint后,就得通过 Advice
确定具体时机与逻辑,是切面代