Spring IOC、DI、AOP以及Spring MVC面试原理(1)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Spring IOC、DI、AOP以及Spring MVC面试原理(1)

Spring IOC加载流程:

初始化ApplicationContext;ApplicationContext实现类中完成的

通过BeanDefinitionReader加载配置文件,并封装成BeadDefinition

将BeanDefinition包装成BeanWrapper

将BeanWrapper保存至IOC容器中


(1)读取配置文件:通过ResourceLoader的getResource方法将类路径,URL,文件系统等方式读为Resource

(2)解析配置文件:解析是在BeanDefinitionReader中完成的,最常用的类是XMLBeanDefinitionReader来完成的,解析涉及到很多步骤,最常见的是将XML文件读取成Document文档,DefaultBeanDefinitionDocumentReader对Document对象进一步解析,DefaultBeanDefinitionDocumentReader又委托给BeanDefinitionParserDelegate进行解析,如果是标准的XML Namespace元素,则会委托合适的NameSpaceHandler进行解析最终解析的结果封装为BeanDefinitionHolder至此解析完成。

(3)Bean的注册:bean的注册是在BeanFactory里完成的,BeanFactory最常见的一个实现类是DefaultListableBeanFactory,,它实现了BeanDefinitionRegistry接口,所以其中的registerBeanDefinition()方法,可以对BeanDefinition进行注册这里附带一提,最常见的XmlWebApplicationContext不是自己持有BeanDefinition的,它继承自AbstractRefreshableApplicationContext,其持有一个DefaultListableBeanFactory的字段,就是用它来保存BeanDefinition所谓的注册,其实就是将BeanDefinition的name和实例,保存到一个Map中。刚才说到,最常用的实现DefaultListableBeanFactory,其中的字段就是beanDefinitionMap,是一个ConcurrentHashMap。

(4)实例化:注册也完成之后,在BeanFactory的getBean()方法之中,会完成初始化,也就是依赖注入的过程


Spring DI加载流程:

Spring DI的基本流程:

(1)循环读取BeanDefinition的缓存信息

(2)调用getBean方法创建对象实例

(3)将创建好的对象实例包装BeanWrapper对象

(4)将BeanWrapper对象缓存到IOC容器

(5)循环IOC容器执行注入


实例化策略根据配置实现不同的策略,将其封装为BeanWrapper

SimpleInstantiationStrategy

实例化有两种情况?

目标类配置了AOP,实例化对象代理类

目标类没有配置AOP,实例化原生对象


为什么要使用BeanWrapper?

统一一个对外访问对象的入口

扩展一些功能,缓存一些配置信息


DI原理:

**FactoryBean.getBeans()**触发依赖注入

createBeanInstance->用反射创建了对象实例->封装成BeanWrapper();

populateBean()–>根据beanName、BeanDefinition、BeanWrapper找到需要赋值的属性,把需要


赋值的属性封装为一个集合,集合的元素是PropertyValue,PropertyValue保存了需要赋值的Bean,赋值需要调用的方法,要赋什么值。


applyPropertyValues() 循环PropertyValue,挨个调用BeanWrapper的setValue()方法,用反射代用setter方法完成赋值。


DI是依赖注入,当IOC容器完成初始化后,针对非懒加载的Bean进行依赖注入或者当第一次getBean时


1)实例化 通过反射机制实例化Bean


2)依赖注入 判断其field是否有需要被注入的属性,如果有则进行注入该依赖的Bean属性


3) 循环依赖的问题,可以通过多级缓存来解决,二级缓存,三级缓存


Spring循环依赖三级缓存是否可以去掉第三级缓存?


image.png


BeanFactory是ApplicationContext的父类


BeanFactory与FactoryBean的区别:

BeanFactory是管理Bean的工厂

FactoryBean是创建对象的工厂Bean


Spring AOP面向切片编程:

基本概念:

(1)切面(Aspect)

 切面是一个横切关注点的模块化,一个切面能够包含同一个类型的不同增强方法,比如说事务处理和日志处理可以理解为两个切面。切面由切入点和通知组成,它既包含了横切逻辑的定义,也包括了切入点的定义。 Spring AOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中。


(2) 目标对象(Target)

 目标对象指将要被增强的对象,即包含主业务逻辑的类对象。或者说是被一个或者多个切面所通知的对象。


(3) 连接点(JoinPoint)

 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。连接点由两个信息确定:


方法(表示程序执行点,即在哪个目标方法)

相对点(表示方位,即目标方法的什么位置,比如调用前,后等)

 简单来说,连接点就是被拦截到的程序执行点,因为Spring只支持方法类型的连接点,所以在Spring中连接点就是被拦截到的方法。

(4) 切入点(PointCut)

 切入点是对连接点进行拦截的条件定义。切入点表达式如何和连接点匹配是AOP的核心,Spring缺省使用AspectJ切入点语法。

 一般认为,所有的方法都可以认为是连接点,但是我们并不希望在所有的方法上都添加通知,而切入点的作用就是提供一组规则(使用 AspectJ pointcut expression language 来描述) 来匹配连接点,给满足规则的连接点添加通知。


(5) 通知(Advice)

 通知是指拦截到连接点之后要执行的代码,包括了“around”、“before”和“after”等不同类型的通知。Spring AOP框架以拦截器来实现通知模型,并维护一个以连接点为中心的拦截器链。


前置通知(Before)指某连接点之前执行的通知,但这个通知不能阻止连接点之前的代码的执行。

后置通知(After)指当某连接点退出时执行的通知(无论是正常返回还是异常退出)

返回后通知(After Return Advice)是某个连接点正常完成通知后执行的通知,不包括抛出异常的情况。

环绕通知(Around Advice)围绕在连接点前后,比如一个方法调用前后

异常通知(After Throwing Advice)是在方法抛出异常导致退出时执行的通知。

(6) 织入(Weaving)

 织入是将切面和业务逻辑对象连接起来, 并创建通知代理的过程。织入可以在编译时,类加载时和运行时完成。在编译时进行织入就是静态代理,而在运行时进行织入则是动态代理。


(7) 增强器(Adviser)

 Advisor是切面的另外一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。Advisor由切入点和Advice组成。

 Advisor这个概念来自于Spring对AOP的支撑,在AspectJ中是没有等价的概念的。Advisor就像是一个小的自包含的切面,这个切面只有一个通知。切面自身通过一个Bean表示,并且必须实现一个默认接口。

 简单来讲,整个 aspect 可以描述为: 满足 pointcut 规则的 joinpoint 会被添加相应的 advice 操作。


两个步骤

AOP的入口:AOP的入口是由接入BeanPostProcessor后置处理器开始的,在bean初始化后提供回调入口,在AbstractAutowireCapableBeanFactory中initializeBean()方法中添加BeanPostProcessor后置处理器。


创建代理类:1,PostProcessAfterInitialization()方法中调用了wrapIfNecessary(),如果代理类实现了接口,使用JDK动态代理,如果没有实现接口,使用cglib动态代理。


代码织入:1,在JDK动态代理类中,如果动态代理类会实现InvokeHandler接口重写invoke方法,在Invoke方法中会通过getInterceptorsAndDynamicInterceptionAdvice方法从提供的配置实例config中获取Advisor列表,遍历处理这个Advisor切面,如果是PointCutAdvisor,则判断此Advisor能否应用到目标方法Method上,将满足条件的Advisor通过AdvisorAdapter转化为MethodInterceptor拦截器列表返回。接下来在Invoke中判断拦截器是否为空,如果为空,则直接调用Method.Invoke反射方法,如果拦截器列表不为空,则调用ReflectiveMethodInvocation.proceed()方法触发执行链的执行,Proceed()串其了整个Interceptor调用链。


image.png


两个重要的类:intercept 拦截器,责任链组件 invoke()

invocation 调用器,嗲用通知回调的组件,procceed()


目录
相关文章
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
76 2
|
4月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
4月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
25天前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
1月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
5月前
|
Java 应用服务中间件 开发者
Java面试题:解释Spring Boot的优势及其自动配置原理
Java面试题:解释Spring Boot的优势及其自动配置原理
130 0
|
2月前
|
设计模式 缓存 Java
面试题:谈谈Spring用到了哪些设计模式?
面试题:谈谈Spring用到了哪些设计模式?
|
2月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
149 9
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
3月前
|
缓存 Java 数据库
【Java面试题汇总】Spring篇(2023版)
IoC、DI、aop、事务、为什么不建议@Transactional、事务传播级别、@Autowired和@Resource注解的区别、BeanFactory和FactoryBean的区别、Bean的作用域,以及默认的作用域、Bean的生命周期、循环依赖、三级缓存、