Ioc的概念
IoC(Inversion of Control)指控制反转,是Spring中的一种设计思想以及重要特性。
IoC意味着将设计好的类交给容器控制,而不是在对象内部控制。
控制,指的是容器控制对象,在传统的开发中,我们通过在对象内部new进行对象创建,而IoC中专门有一个创建对象。
反转指的是获取对象的方式发生了反转,以往对外部资源或对象的获取依赖于程序主动通过new引导,现在则是通过容器实现。容器帮我们查找并注入依赖对象。
IoC是一条面向对象的重要法则,可以指导我们设计出松耦合的程序,使得程序的系统结构变得非常灵活。
IoC的启动过程
(以ClassPathXmlApplicationContext为例)
- 进入构造函数,并先调用父类的的构造函数
- 根据提供的路径,处理配置文件数组,对应方法为:setConfigLocations(configLocations)
- 执行 Refresh 方法,该方法可以反复调用,销毁当前 ApplicationContext 并重新执行一次初始化操作,对应方法为:refresh()
- 进入 Refresh 方法后,首先进入同步块
- 然后执行准备工作,记录容器启动时间,标记当前状态为已启动并处理文件占位符,对应方法为:prepareRefresh();
- 执行 Bean 的加载、解析、注册,使得静态 XML 变为 BeanDefinition ,并注册到 BeanFactory 中。这里只是提取 Bean 的配置信息而非初始化;创建并初始化 BeanFactory 。对应方法为—— obtainFreshBeanFactory()
- 设置 BeanFactory 的类加载器,添加 BeanPostProcessor 接口并手动注册几个特殊的 Bean。对应方法为——prepareBeanFactory(beanFactory)
截止至此,Bean 的加载、解析、注册已经完成;BeanFactory 的创建以及初始化已经完成,如果不是第一次启动还会涉及 BeanFactory 的销毁
- 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法在初始化前做一些用户自定义的行为。对应方法为——postProcessBeanFactory(beanFactory);invokeBeanFactoryPostProcessors(beanFactory)
- 注册 BeanPostProcessor ,对应方法为:registerBeanPostProcessors(beanFactory)
- 做一些额外的初始化:initMessageSource();initApplicationEventMulticaster();onRefresh();registerListeners();
- 对所有可初始化的 SingletonBean 进行初始化,对应方法——finishBeanFactoryInitialization(beanFactory)
- 广播完成状态,对应方法——finishRefresh()
AOP的概念
AOP指面向切面编程,通过预编译方式和运行期动态代理的一种技术。利用AOP可以对业务逻辑的各个部分进行隔离,从而降低业务逻辑各组件的耦合度,提高程序的可重用性,同时提高了开发的效率。
AOP具有以下核心概念:
-
切面:一些Pointcut以及襄阳的Advice的集合
-
连接点:表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它的连接点
-
切点:通过制定某种规则来选定一组连接点,这些连接点或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的增强将要发生的地方
-
增强:定义了在切点里面定义的程序点具体要做的操作
-
目标对象:织入增强的目标对象
-
织入:将切面和其他对象连接起来, 并创建增强的过程
AOP的实现原理
AOP基于动态代理模式实现,代理模式允许调用者在不改变被调用者方法的前提下,通过代理对象对目标方法进行扩展。
在AOP的设计中,每个Bean都会被JDK或cglib代理并有多个方法拦截器。拦截器分为两层,外层由Sping内核控制,内层拦截器由用户设置。当代理方法被调用时,先经过外层拦截器,外层拦截器根据方法提供的信息判断哪些内层拦截器应该被执行,然后会创建并执行拦截器链,最后调用目标对象的方法。内层;拦截器的设计采用了职责链的设计。
Spring 中 AOP 的实现依赖于动态代理的实现。动态代理主要有两种实现,分别是 JDK 动态代理和 cglib 代理。
采用JDK动态代理,目标类必须实现某个接口,否则不可用;而cglib底层是通过使用一个小而块的字节码处理框架ASM来转换字节码并生成新的类,覆盖或添加类中的方法。
从上述描述中不难看出,cglib类中方法类型不难设置为final。在执行效率上,早期的JDK动态代理效率远低于cglib,而随着JDK版本的更新,现在JDK动态代理的效率以及和cglib不相伯仲。