IoC容器
IoC即控制反转,指将对象的创建与依赖关系管理交给第三方容器负责。
Spring通过IoC容器来管理Java对象的创建与实例化,控制Java对象的依赖关系。
具体实现:DI(依赖注入):在创建对象的过程中,将对象依赖属性通过构造函数,Setter方法等方法注入。
AOP
面向切面编程:将影响多个类的公共行为(如日志,事务,安全等)将业务逻辑中分离出来,通过横切的方法模块化。
核心术语:
- 切面(Aspect):横切关注点的模块化,是一个类,封装了我们要增强的公共逻辑,如
LoggingAspect类,封装了所有的日志操作。 - 通知(Advice):切面中具体要执行的操作。定义了“做什么”以及“何时做”。分为以下五个类型:
@Before:在方法调用之前执行@AfterReturning:在方法成功执行并返回结果之后@AfterThrowing:在方法抛出异常之后@After:在方法执行完毕之后(无论成功失败,类似于finally)@Around:包裹整个执行过程
- 连接点(Join point):连接点,指程序执行过程中的一个点。
- 切点(Pointcut):切点,用于和连接点匹配
代理模式
- 代理模式:提供一个代理类,将非核心逻辑剥离并封装起来,当我们调用目标方法时,通过代理类进行间接调用。
- 静态代理:代码创建,通常指代理一个类。
- 动态代理:要求对象至少实现一个接口,通过创建一个实现同样接口的代理类。在程序运行期间实现,通过反射机制动态创建。
动态代理在Spring中有两种类型:
- 基于JDK的动态代理:需要被代理类实现一个接口。
- 基于CGLIB的动态代理:当检测到被代理类没有实现接口,Spring就会使用第三方库通过继承生成被代理类的子类作为代理类。
三级缓存
解决问题:通过setter方法进行依赖注入且是在单例模式下产生的循环依赖问题。
使用三个重要的缓存(Map实现),成为三级缓存:
singletonObjects:存放完全初始化好的Bean实例(实例化,属性填充,生成AOP代理类)earlySingletonObjects:存放提前暴露的Bean的原始对象引用 或 早期代理对象引用。- 当一个Bean还在创立过程中,但他的引用需要被注入到另一个Bean中,就暂时放在这里。避免重复生成代理
singletonFactories:存放Bean的ObjectFactory工厂对象- 当 Bean 被实例化后(刚调完构造函数),Spring 会创建一个
ObjectFactory并放入三级缓存。 - 这个工厂的
getObject()方法负责返回该 Bean 的早期引用(可能是原始对象,也可能是提前生成的代理对象),当检测到循环依赖需要注入一个尚未完全初始化的 Bean 时,就会调用这个工厂来获取早期引用。
- 当 Bean 被实例化后(刚调完构造函数),Spring 会创建一个
过程(两个类,其中BeanA依赖于BeanB,BeanB也依赖于BeanA):
- 创建BeanA,先调用BeanA的构造函数实例化,得到原始对象。此时生成BeanA的
ObjectFactory工厂对象并放入三级缓存。 - 注入BeanA,此时遇到BeanB的依赖,容器转向BeanB的制造。
- 创建BeanB,将BeanB实例化,生成的
ObjectFactory工厂对象放入三级缓存,填充时发现依赖于BeanA,去缓存中进行查找:- 一级缓存中没有
- 二级缓存中没有
- 三级缓存中有BeanA的
ObjectFactory工厂对象,调用getObject():- 如果BeanA需要代理,则生成代理类
- 若不需要,则生成原始类
- 取出生成BeanA的半成品放入二级缓存,同时清理三级缓存,最后注入BeanB。
- 将BeanB初始化,并放入一级缓存中,清除二三级缓存,之后进入生命周期正常使用。
- 继续初始化BeanA,将一级缓存中完整的BeanB取出注入BeanA,BeanA进入一级缓存,删除二级缓存。
Bean
生命周期:
-
加载Spring Bean:通过XML、Java annotation(注解)以及Java Configuration(配置类)等方式加载Spring Bean,即告诉Spring框架需要创建哪些Bean。
-
解析Bean的定义:将配置文件中的<bean>标签转换为Spring框架内部使用的数据结构,类似于XML解析。
BeanDefinitionReader:解析器,将Bean的定义解析成Spring内部的BeanDefinition结构。BeanDefinition:Bean的元数据,包含Bean的各种属性和方法,例如id(标识符)、class(类名)、scope(作用域)、ref(依赖的Bean)等,实际上是将配置文件中的标签的定义信息存储到对应的BeanDefinition属性中。
-
BeanFactoryPostProcessor :Spring容器的扩展接口,可以对
BeanDefinition进行加工处理,例如填充或修改BeanDefinition的属性。 -
实例化Bean对象:
BeanFactory根据配置文件中的BeanDefinition信息来实例化Bean对象,并进行属性赋值。(根据class属性反射机制实例化对象,反射赋值设置属性) -
Aware感知:Aware 感知允许在Bean的生命周期中获取对Spring容器的访问权限。通过实现相应的Aware接口,Bean可以获得与Spring容器的交互能力。在Spring框架中,有多个Aware接口可供实现:
-
BeanNameAware:通过实现BeanNameAware接口,Bean可以获取自己在Spring容器中的名称。 -
ApplicationContextAware:通过实现ApplicationContextAware接口,Bean可以获取对Spring应用上下文的引用。 -
BeanFactoryAware:通过实现BeanFactoryAware接口,Bean可以获取对Spring Bean工厂的引用。 -
初始化方法:如果Bean定义中指定了初始化方法,容器会在属性赋值完成后调用该方法进行一些初始化操作。
- 使用@PostConstruct注解
- 实现InitializingBean接口
- 在Spring配置文件中配置 init-method 属性。
-
后置处理:
BeanPostProcessor:它是一个后置处理器,在Bean对象实例化和依赖注入完成后,在显示调用初始化方法之前或之后添加自定义的逻辑。可以将其类比为AOP中的环绕通知。- 只有当Bean对象实现了BeanPostProcessor接口时,才会执行Before和After方法。
- 执行顺序是:Before方法 -> 初始化Bean(InitializingBean接口和init-method方法)-> After方法。
-
销毁:在Spring容器关闭时调用。在销毁阶段,可以执行一些清理工作,例如释放资源等。
- 使用@PreDestroy注解
- 实现DisposableBean接口
- 配置destroy-method属性
<bean id="paramAction" class="com.ycxw.beanLife.ParamAction" destroy-method="destroy"></bean>
作用域
- Singleton(单例):默认,在容器初始化时被创建一次,存储在容器中,可在后续的请求中重复使用。
- Prototype(原型):每次请求都会创建一个新的Bean实例,适用于状态瞬时的Bean。
- Request(请求):每个HTTP请求都会创建一个新的Bean实例,仅在Spring Web应用程序中有效。
- Session(会话):在Session范围内指挥创建一个新的Bean实例,在用户会话范围内有效。
MVC框架
Model-View-Controller
- 模型(Model):POJO
- 数据承载Bean:承载用户数据,实体类(User)
- 业务处理Bean:处理用户请求,Service
- 视图(View):为用户提供使用页面,与用户进行交互
- 控制器(Controller):将模型与视图分离,将View传来的用户请求转发给相应的Model,并将Model处理过后的结果向用户相应。