Java后端八股笔记4 Spring基础

24 阅读6分钟

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 时,就会调用这个工厂来获取早期引用。

过程(两个类,其中BeanA依赖于BeanB,BeanB也依赖于BeanA):

  1. 创建BeanA,先调用BeanA的构造函数实例化,得到原始对象。此时生成BeanA的ObjectFactory工厂对象并放入三级缓存。
  2. 注入BeanA,此时遇到BeanB的依赖,容器转向BeanB的制造。
  3. 创建BeanB,将BeanB实例化,生成的ObjectFactory工厂对象放入三级缓存,填充时发现依赖于BeanA,去缓存中进行查找:
    1. 一级缓存中没有
    2. 二级缓存中没有
    3. 三级缓存中有BeanA的ObjectFactory工厂对象,调用getObject()
      1. 如果BeanA需要代理,则生成代理类
      2. 若不需要,则生成原始类
    4. 取出生成BeanA的半成品放入二级缓存,同时清理三级缓存,最后注入BeanB。
  4. 将BeanB初始化,并放入一级缓存中,清除二三级缓存,之后进入生命周期正常使用。
  5. 继续初始化BeanA,将一级缓存中完整的BeanB取出注入BeanA,BeanA进入一级缓存,删除二级缓存。

Bean

生命周期:

90667654fc142a66c0c8612ebdbb194c.png

  1. 加载Spring Bean:通过XML、Java annotation(注解)以及Java Configuration(配置类)等方式加载Spring Bean,即告诉Spring框架需要创建哪些Bean。

  2. 解析Bean的定义:将配置文件中的<bean>标签转换为Spring框架内部使用的数据结构,类似于XML解析。

    1. BeanDefinitionReader:解析器,将Bean的定义解析成Spring内部的BeanDefinition结构。
    2. BeanDefinition:Bean的元数据,包含Bean的各种属性和方法,例如id(标识符)、class(类名)、scope(作用域)、ref(依赖的Bean)等,实际上是将配置文件中的标签的定义信息存储到对应的BeanDefinition属性中。
  3. BeanFactoryPostProcessor :Spring容器的扩展接口,可以对BeanDefinition进行加工处理,例如填充或修改BeanDefinition的属性。

  4. 实例化Bean对象BeanFactory根据配置文件中的BeanDefinition信息来实例化Bean对象,并进行属性赋值。(根据class属性反射机制实例化对象,反射赋值设置属性)

  5. Aware感知:Aware 感知允许在Bean的生命周期中获取对Spring容器的访问权限。通过实现相应的Aware接口,Bean可以获得与Spring容器的交互能力。在Spring框架中,有多个Aware接口可供实现:

  6. BeanNameAware:通过实现BeanNameAware接口,Bean可以获取自己在Spring容器中的名称

  7. ApplicationContextAware:通过实现ApplicationContextAware接口,Bean可以获取对Spring应用上下文的引用。

  8. BeanFactoryAware:通过实现BeanFactoryAware接口,Bean可以获取对Spring Bean工厂的引用。

  9. 初始化方法:如果Bean定义中指定了初始化方法,容器会在属性赋值完成后调用该方法进行一些初始化操作。

    1. 使用@PostConstruct注解
    2. 实现InitializingBean接口
    3. 在Spring配置文件中配置 init-method 属性。
  10. 后置处理BeanPostProcessor:它是一个后置处理器,在Bean对象实例化和依赖注入完成后,在显示调用初始化方法之前或之后添加自定义的逻辑。可以将其类比为AOP中的环绕通知。

    1. 只有当Bean对象实现了BeanPostProcessor接口时,才会执行Before和After方法。
    2. 执行顺序是:Before方法 -> 初始化Bean(InitializingBean接口和init-method方法)-> After方法。
  11. 销毁:在Spring容器关闭时调用。在销毁阶段,可以执行一些清理工作,例如释放资源等。

    1. 使用@PreDestroy注解
    2. 实现DisposableBean接口
    3. 配置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处理过后的结果向用户相应。