剑指Java面试-Spring整理(不定期更新!)
一、Spring IoC介绍
IOC(Inversion of Control):控制反转
- Spring Core最核心的部分
- 依赖注入(Dependency Inversion):把底层类作为参数传递给上层类,实现上层对下层的“控制”
DI举例:设计行李箱
上述依赖关系转换成代码如下所示:
如果我们这里假设我们需要改动轮胎类Tire的尺寸,由于我们这里的上层建筑都是依赖下层建筑的,所以我们就必须得这样改了,如下图:
由此我们可以看到,我们仅仅只是为了修改轮胎的大小这么一个参数,这种设计就需要修改整个上层所有类的构造函数,在软件工程中这种设计几乎是不可维护的。
现在我们来换种思路:
先设计行李箱的大概样子,根据行李箱的样子来设计箱体,再根据箱体来设计底盘,再根据底盘来设计轮子,这时候的依赖关系相比之前就倒置过来了,轮子依赖于底盘,底盘依赖于箱体,箱体依赖于行李箱,而这就是所谓的控制反转,即上层控制下层,而不是下层控制上层,用依赖注入来实现这种控制反转。
- 依赖注入(Dependency Inversion):把底层类作为参数传递给上层类,实现上层对下层的“控制”
这时的代码是这样子的:
这时如果我们想要修改轮子的大小,只需要进行很小的修改便可以了,如下图:
1. IOC、DI、DL的关系
- Dl:依赖查找,侵入性更强,已经被抛弃
- DI:依赖注入
2. 依赖注入的方式
- Setter
- Interface
- Constructor
- Annotation
3. 依赖倒置原则、IOC、DI、IOC容器的关系
4. IOC容器的优势
- 避免在各处使用new来创建类,并且可以做到统一维护
- 创建实例的时候不需要了解其中的细节
一、Spring IoC容器
Spring启动时去读取应用程序提供的Bean配置信息,并在Spring容器中生成一份Bean定义注册表,然后根据这张注册表去实例化Bean,装配好Bean之间的依赖关系,为上层提供准备就绪的依赖环境。Spring提供一个配置文件描述Bean和Bean之间的依赖关系,利用Java的反射功能实例化Bean并建立Bean之间的依赖关系
1.Spring IoC支持的功能
- 依赖注入
- 依赖检查
- 自动装配
- 支持集合
- 指定初始化方法和销毁方法
- 支持回调方法
2. Spring IoC容器的核心接口
- BeanFactory
- ApplicationContext
BeanDefinition
- 主要用来描述Bean的定义
Spring容器会将XMl或者注解里的Bean的定义解析成Spring内部的BeanDefinition
BeanDefinitionRegistry
- 提供向IOC容器注册BeanDefinition对象的方法
BeanFactory:Spring框架最核心的接口
- 提供IOC的配置机制
- 包含Bean的各种定义,便于实例化Bean
- 建立Bean之间的依赖关系
- Bean生命周期的控制
BeanFactory体系结构
BeanFactory与ApplicationContext的比较
ApplicationContext是BeanFactory的子接口之一
- BeanFactory是Spring框架的基础设施,面向Spring
- ApplicationContext面向使用Spring框架的开发者
ApplicationContext的功能(继承多个接口)
- BeanFactory:能够管理、装配Bean
- ResourcePatternResolver:能够加载资源文件
- MessageSource:能够实现国际化等功能
- ApplicationEventPublisher:能够注册监听器,实现监听机制
3. getBean方法的代码逻辑:
- 转换beanName
- 从缓存中加载实例
- 实例化Bean
- 检测parentBeanFactory
- 初始化依赖的Bean
- 创建Bean
4. Spring Bean的作用域
- singleton:Spring的默认作用域,容器里拥有唯一的Bean实例
- prototype:针对每个getBean请求,容器都会创建一个Bean实例
- request:会为每个Http请求创建一个Bean实例
- session:会为每个session创建一个Bean实例
- globalSession:会为每个全局HttpSession创建一个Bean实例,该作用域仅对Portlet有效
5. Spring Bean的生命周期
创建过程
销毁过程:
- 若实现了DisposableBean接口,则会调用destroy方法
- 若配置了destry-method属性,则会调用其配置的销毁方法
三、Spring AOP
关注点分离:不同的问题交给不同的部分去解决
- 面向切面编程AOP正是此种技术的体现
- 通用化功能代码的实现,对应的就是所谓的切面(Aspect)
- 业务功能代码和切面代码分开后,架构将变得高内聚低耦合
- 确保功能的完整性:切面最终需要合并到业务中(Weave)
1. AOP的三种织入方式:
- 编译时织入:需要特殊的Java编译器,如AspectJ
- 类加载时织入:需要特殊的Java编译器,如AspectJ和AspectWerkz
- 运行时织入:Spring采用的方式,通过动态代理的方式,实现简单
2. AOP的主要名词概念
- Aspect: 通用功能的代码实现
- Target:被织入Aspect的对象
- Join Point:可以作为切入点的机会,所有方法都可以作为切入点
- Pointcut:Aspect实际被应用在的Join Point,支持正则
- Advice:类里的方法以及在这个方法如何织入到目标方法的方式
- Weaving:AOP的实现过程
3. Advice的种类
- 前置通知(Before)
- 后置通知(AfterReturning)
- 异常通知(AfterThrowing)
- 最终通知(After)
- 环绕通知(Around)
四、Spring AOP的原理
AOP的实现,JdkProxy和Cglib
- 由AopProxyFactory根据AdvisedSupport对象的配置来决定
- 默认策略如果目标类是接口,则用JDKProxy来实现,否则用后者
- JDKProxy的核心:InvocationHandler接口和Proxy类
- Cglib:以继承的方式动态生成目标类的代理
1. JdkProxy和Cglib的实现
- JDKProxy:通过Java内部的反射机制实现
- Cglib:借助ASM实现
- 反射机制在生成类的过程中比较高效
- ASM在生成类之后的执行过程中比较高效
2. 代理模式
代理模式:接口 + 真实实现类 + 代理类
Spring里代理模式的实现:
- 真实实现类的逻辑包含在了getBean方法里
- getBean方法返回的实际上是Proxy的实例
- Proxy实例是Spring采用JDK Proxy或者CGLIB动态生成的