01.Spring框架的基本理解
关键字:核心思想IOC/AOP,作用(解耦,简化),简单描述框架组成;
Spring框架是一款轻量级的开发框架,核心思想是IOC(反转控制)和AOP(面向切面编程),为Java应用程序开发提供组件管理服,用于组件之间的解耦,以及简化第三方JavaEE中间件技术的使用(JMS,任务调度,缓存,ORM框架),是一个基础架构型的开发框架;
Spring框架包括:IOC容器,Validation数据校验,AOP面向切面编程,Transactions事务管理,Spring JDBC,Spring MVC框架,以及第三方JavaEE中间件技术集成;
02.Spring框架由哪些模块组成
关键字:官方文档描述,由7个模块组成
Spring Framework根据官方文档的描述,主要包括以下常用5个模块:
1、Core:核心模块
包括:Ioc Container(Ioc容器),Events(事件通知机制),Resources(资源加载机制),i18n(国际化),Validation(数据校验),Data Binding(数据绑定),Type Conversion(类型转换),SpEL(Spring表达式),AOP(面向切面编程);
2、Testing:测试模块
包括:Mork Objects(测试模拟对象),TestContext Framework(测试框架),Spring MVC Test(用于测试Spring MVC),WebTestClient(用于测试WebClient,Restful,Webflux等);
3、Data Access:数据访问模块
包括: Transactions (事务管理),DAO Support(统一的 Data Access object DA0模式封装),JDBC(Spring 对于 JDBC 的操封装),0/R Mapping (Spring 对于对象关系映射框架的封装,例如 Hibernate 等框架)等;
4、Web Servlet:基于Servlet的Web应用开发
包括: Spring MVC(Spring 基于 MVC 模式设计封装的 Web 架),WebSocketSpring 集成 WebSocketWebsocket是一个服务器与客户端双向通信的技术)等;
5、Integration:企业级系统集成模块 (不同系统之间的交互集成)
包括:Remoting (spring用于在分布式系统中进行远程服务调用的通讯框架),JM(Spring集成各类Java消息中间件、Java消息服务[Java Message Service],例如ActiveMo6等),Java Email (邮件发送),Tasks Scheduling (任务调度);
03.SpringIOC的理解
关键字: IOC名词解释,作用是解耦,使用 IOC 容器管理项目组件之间的合关系
Ioc(Inversion of control,中文释义: 控制反转)是 Spring 架的核心思想之,主要用于解耦。 IOC 是指将创建对象的控制权转移给 pring 框架进行管理。由 Spring框架根据配置文件或注解等方式,创建 bean 对象并管理各个bean 对象之间的依赖关系。使对象之间形成松散耦合的关系,实现解耦;
控制:指的是对象创建(实例化、管理)的权力
反转:控制权交给外部环境(Spring框架IoC容器)
04.Spring IOC容器的理解
关键字: IOC容器的作用、存储形式、初始化过程
IOC通常被理解为 IOC Container 容器, IOC 容器其实就是一个 Map, key 是每个bean对象的 ID,value是 bean 对象本身。 IOC容器负责创建 bean 对象并管理 bean的生命周期。并且根据配置好配置文件或注解,管理 IOC 容器中的每个 bean,以及根据 bean 之间的依赖关系,完成 bean 之间的注入。
IOC 容器属于 Spring Core 模块,用来创建和管理 Bean ,默认使用单例的方式将bean存储在 DefaultListableBeanFactory 类的 beanDefinitionMap中(一个ConcurrentHashMap 类型的Map集合);
IOC容器使用 ConcurrentHashMap 集合存储了 BeanDefinition 对象,该对象封装了Spring对一个 Bean 所有配置信息,包括: 类名,属性,构造方法参数,依赖,是否延迟加载,是否是单例等配置信息:
05.Spring DI的理解
关键字:名词解释 是一种通过容器自动将依赖对象注入到目标对象中的机制
DI(Dependecy Inject ,中文释义:(依赖注入) 是对 IOC概念的不同角度的描述,是指应用程序在运行时,每一个 bean 对象都依赖IOC容器注入当前 bean 对象所需要的另个 bean 对象。(例如在MyBatis 整合 Spring时,SqlSessionFactorvBean赖IOC容器注入一个 DataSource 数据源 bean );
06.什么是Spring的bean
简单来说, Bean 代表被 IoC 容器管理的对象。
我们通过配置文件或注解,告诉 oc 容器帮助我们管理哪些对象
07.将一个类声明为Bean的注解有哪些
@Component:定义通用Bean的注解,可标注任意类为 Bean 。如果一个 Bean 不知道属于哪个层,可以使用 @Component 注解标注;
@Repository:定义数据访问层Bean的注解;
@Service :定义业务层Bean的注解;
@Controller:定义控制器Bean的注解;
08.@Component和@Bean的区别是什么
@Component 注解作用于类,而 @Bean 注解作用于方法;
@Component 通常是通过类路径扫描来实现自动扫描并完成装配 Bean 到 Spring IOC 容器中;
@Bean 注解通常用于注解某个方法,通过 @Bean 注解告诉了 Spring IOC 容器,该方法的返回值实例是一个 Bean。
09.@Autowired和@Resource的区别是什么
@Autowired 是 Spring 提供的注解,@Resource 是JDK 提供的注解;
@Autowired 默认的注入方式为 byType(按类型自动注入),@Resource 默认输入方式为 byName(按名称自动注入)。
10.Spring框架中的常见注入方式有几种
Spring IOC 有三种注入方式: 构造注入、Setter注入、属性注入;
构造注入:使用构造方法注入 bean ;
Setter注入:使用Setter方法注入 bean ;
属性注入:使用成员属性注入 bean ,不推荐。原因:使用私有的成员属性变量,依靠反射实现,破坏封装,只能依靠 IOC 容器实现注入,不严谨;
11.Spring中常见的ApplicationContext实现类有哪些
classPathXmlApplicationContext : 根据项目类路径 classpath 下的配置文件加载 bean;
FileSystemXmlApplicationContext:根据当前磁盘的一个绝对系统文件路径下的配置文件加载bean;
AnnotationConfigApplicationContext : 根据读取到的注解加载 bean;
WebApplicationContext : Web 容器下按照配置文件加载 bean ;
12.BeanFactory和ApplicationContext有什么区别
两者之间的关系: BeanFactory 和 ApplicationContext 是Spring 的两大核心接口都可以当做Spring的容器;
两者区别与不同:
BeanFactory 是spring 里面最底层的接口,是IOC的核心,定义了IOC的基本功能,包含了各种 Bean 的定义、加载、实例化,依赖注入和生命周期管理等行为;
ApplicationContext 接口作为 BeanFactory 接口的子接口,包含 BeanFactory 所具备的功能外,还提供了其它框架功能: 继承 MesageSource (支持国际化)资源文件访问、可以同时加载多个配置文件、可以通过监听器管理 bean 的生命周期;
Bean的创建加载方式:
BeanFactroy 采用的是延迟加载形式来注入 Bean,只有在使用到某个 Bean 时,才对该Bean 进行加载实例化。这样不能提前发现一些存在的 Spring的配置问题。如果Bean 的某一个属性没有注入, BeanFacotry 加载后,直至第一次使用调用 getBean()方法才会抛出异常;
ApplicationContext 是在容器启动时,一次性创建了所有的 Bean 。这样,在容器启动时,我们就可以发现 spring 中存在的配置错误,这样有利于检查所依赖属性是否注入。ApplicationContext 启动后预载入所有的单实例 Bean,所以在运行的时候速度比较快,因为它们已经创建好了。相对于 BeanFactory,ApplicationContext唯一的不足是占用内存空间,当应用程序配置 Bean 较多时,程序启动较慢。
13.Spring框架启动流程
首先,初始化 Spring 容器,注册内置的 BeanPostProcessor 的 BeanDefinition 到容器中;
实例化 BeanFactory[ DefaultListableBeanFactory ]工厂,用于生成 Bean对象;
实例化 BeanDefinitionReader ,用于读取 Spring 配置文件或注解,将配置文件中Spring 需要 管理的组件类,转化成 BeanDefinition 对象,( BeanDefinit中极甘重要的个艇今对免的所有特 征信自夜佬aN例如: Bean的ID,是否单例,是否懒加载等);
实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找bean 对象;
将配置类的BeanDefinition注册到容器中;
调用refresh0方法刷新容器;
prepareRefresh()刷新前的预处理;
obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory;
prepareBeanFactory(beanFactory): BeanFactory的预处理工作,向容器中添加一些组件
postProcessBeanFactory(beanFactory): 子类重写该方法,可以实现在BeanFactory创建并预 处理完成以后做进一步的设置;
invokeBeanFactoryPostProcessors(beanFactory): 在BeanFactory标准初始化之后执行 BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器:
registerBeanPostProcessors(beanFactory): 向容器中注册Bean的后置处理器 BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理自动注入、循环依赖等功能
initMessageSource(): 初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息 解析:
initApplicationEventMulticaster(): 初始化事件派发器,在注册监听器时会用到:
onRefresh(): 留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑;
registerListeners(): 注册监听器: 将容器中所有的ApplicationListener注册到事件派发器中,并 派发之前步骤产生的事件;
finishBeanFactorylnitialization(beanFactory): 初始化所有剩下的单实例bean,核心方法是prelnstantiateSingletons(),会调用getBean0方法创建对象;
finishRefresh():发布BeanFactory容器刷新完成事件。
14.Spring框架中的Bean的作用域
singleton:Spring只会为该bean对象创建唯一实例,Spring中的bean默认都是单例;
prototype:每次获取bean,Spring会创建一个新的bean实例;
request:每一次HTTP请求,Spring会创建一个新的bean实例;
session:不同的HTTP会话,Spring会创建不同的bean对象。
15.Spring框架中的Ben的线程安全
对于prototype作用域的Bean,每次都会创建一个新的对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题;
对于 singleton 作用域的 Bean,所有的线程都共享一个单例状态的 Bean,存在资源竞争,因此是存在线程安全问题;
对于 singleton 作用域的单例 bean ,它的线程安全问题,常见有两种解决办法:
1、在bean 中尽量避免定义可变的成员变量(用于保存数据的成员变量);
2、在类中定义一个ThreadLocal成员变量,将需要可变的成员变量保存在ThreadLocal中。
16.Spring框架中的Bean生命周期
Spring的生命周期总体分为四个阶段:实例化=>属性注入=>初始化=>销毁
Step1 实例化 Bean: 根据配置文件中 Bean 的定义,利用 Java Reflection 反射技术创建Bean的实例;
1、加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefifinition对象;
2、将BeanDefifinition存储在一个名为beanDefifinitionMap的Map<String,BeanDefifinition>中;
3、ApplicationContext底层遍历beanDefifinitionMap,创建Bean实例对象;
4、创建好的Bean实例对象,被存储到一个名为singletonObjects的Map<String,Object>中;
5、当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回
Step2 注入对象依赖的属性值 (或对象)
Spring在进行属性注入时,会分为如下几种情况:
1、注入普通属性,String、int或存储基本类型的集合时,直接通过set方法的反射设置进去;
2、注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;
3、注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖),使用三级缓存解决;
Step3 处理各种Aware接口:Spring 会检测该 Bean 是否实现了 xxxAware 接口,通过Aware类型的接口,可以让Spring框架为当前 Bean注入相应的内容
如果 Bean 实现 BeanNameAware 接口,会调用它实现的 setBeanName(String beanId)方 法,注入 Bean的名字;
如果 Bean 实现 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,注入 classLoader 对象的实例;
如果 Bean 实现 BeanFactoryAware 接口,会调用它实现的 setBeanFactory()方法,注入的是 Spring 工厂;
如果 Bean 实现 ApplicationContextAware 接口,会调用 setApplicationContext()方法,注入 Spring 上下文;
Step4 执行BeanPostProcessor前置处理: 如果想对 Bean 进行一些自定义的前置处理,那么可以让 Bean 实现了 BeanPostProcessor 接口,将会在该阶段调用postProcessBeforeInitialization(Object obj,String s)方法。
Step5 执行InitializingBean初始化方法:如果 Bean 实现了 InitializingBean 接口,执行 afeterPropertiesSet() 方法。
Step6 执行init-method自定义初始化方法:如果 Bean 在Spring 配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法;
Step7 执行BeanPostProcessor后置处理: 如果这个 Bean 实现了BeanPostProcessor接口将会调用 postProcessAfterInitialization(Object obj,String s)方法,由于这个方法是在 Bean初始化结束后调用;
以上几个步骤完成后Bean已经被正确创建,可以正常使用这个 Bean了
Step8 执行DisposableBean销毁Bean:当 Bean 不再需要时,会经过清理阶段,如果 Bean实现了 DisposableBean 这个接口,会调用其实现的 destroy()方法执行销毁;
Step9 执行destroy-method自定义销毁方法: 如果这个 Bean 的 Spring 配置中配置了destroy-method 属性,会自动调用其配置的自定义销毁方法。
17.Spring框架如何解决循环依赖
循环依赖问题是指:类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。例如A类依赖了B类,B类依赖了C类,而最后C类又依赖了A类,这样就形成了循环依赖问题。
多个实体之间相互依赖并形成闭环的情况就叫做"循环依赖",也叫做"循环引用
Spring提供了三级缓存存储 完整Bean实例和半成品Bean实例,用于解决循环依赖问题。
在DefaultListableBeanFactory的上四级父类DefaultSingletonBeanRegistry中提供如下三个Map:
public class DefaultSingletonBeanRegistry ... { //1、最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存" Map<String, Object> singletonObjects = new ConcurrentHashMap(256); //2、早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存" Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16); //3、单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三级缓存" Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16); } 注:将对象保存至三级缓存的时候,会包装成ObjectFactory对象录入,未来通过此接口对应的get方法再次提取对象
18.Spring框架中有哪些注解
用于声明Bean的注解:
@Component:定义通用Bean的注解,可标注任意类为 Bean 。如果一个 Bean 不知道属于哪个层,可以使用 @Component 注解标注;
@Repository:定义数据访问层Bean的注解;
@Service :定义业务层Bean的注解;
@Controller :定义控制器Bean的注解。
用于注入的注解:
@Autowired:按类型自动注入;
@Qualifier: 按名称自动注入;
声明配置、扫描、启用特性的注解:
@Configuration : 声明配置类;
@ComponentScan :组件扫描;
@EnableScheduling : 启用任务调度;
@EnableAspectJAutoProxy : 启用自动代理工厂
19.Spring框架中用到的设计模式
工厂模式:Spring 使用工厂模式,通过 BeanFactory 或ApplicationContext 来创建对象;
单例模式:Bean 默认作用域为单例,按照单例设计模式进行设计实现;
策略模式:Resource的实现类,针对不同的资源文件,实现了不同方式的资源获取策略;
代理模式:Spring的AOP的实现依靠动态代理(JDK的反射和CGLIB);
模板方法:Spring 提供了 JdbcTemplate,RedisTemplate 等模板对象,将相同的操作步骤进行了封装;
适配器模式:Spring AOP 的增强或通知 ( Advice )使用到了适配器模式, Spring MVC中也用到了适配器模式适配 Controller;
20.Spring框架中AOP的基本理解
AOP (Aspect-0riented Programming:面向切面编程):将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为“切面” ( Aspect ),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;
Spring AOP基于动态代理实现:
如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy (反射),基于接口的方式,创建代理对象 (JDK 动态代理的核心是 InvocationHandler接口和Proxy类);
如果被代理的对象,没有实现某个接口,就无法使用JDK Proxy去进行代理了,这时候 Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理(Cglib 动态代理的核心是 MethodInterceptor 接口和 Enhancer 类);
21.Spring AOP和AspectJ AOP有什么区别
Spring AOP 已经集成了 AspectJ,AspectJ是一个 Java 技术生态系统中实现AOP编程思想的独立框架; AspectJ相比于 Spring AOP 能更加强大,但是 Spring AOP相对来说更简单更容易;
Spring AOP属于运行时增强,而 AspectJ是编译时增强;
Spring AOP 基于动态代理( Proxying ),而 AspectJ 基于字节码操作( Bytecode Manipulation );
如果项目中的切面代码比较少,两者性能差异不大。如果切面代码太多的话,最好选择AspectJ,因为基于字节码操作的缘故,AspectJ比 Spring AOP 从性能上要快很多。
22.Spring AOP有哪些通知类型
前置通知:实现 MethodBeforeAdvice 接口,在目标方法调用前,执行通知;
环绕通知:实现 MethodInterceptor 接口,是一个包围目标方法的通知。环绕通知可以在方法调用先后完成定义的行为;
后置通知:实现AfterReturningAdvice 接口,在在目标方法调用后,执行通知(如果方法抛出异常,则不执行通知) ;
异常通知:实现 ThrowsAdvice 接口,在方法抛出异常时,执行通知;
返回通知
23.Spring管理事务的方式有几种
编程式事务: 在代码中硬编码 (不推荐使用) :通过 TransactionTemplate 或者 TransactionManager手动管理事务,实际应用中很少使用,用于理解 Spring 事务管理;
声明式事务 : 在 XML配置文件或者基于注解 @Transactional(推荐使用),通过AOP实现。
24.Spring事务中有哪几种事务传播行为
事务传播行为是为了解决业务层方法之间互相调用时,产生事务问题。
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如: 方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。
事务传播行为有如下分类:
1、TransactionDefinition.PROPAGATION REQUIRED
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。@Transactional注解默认使用的事务传播行为。
2、TransactionDefinition.PROPAGATION REQUIRESNEW
创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
3、TransactionDefinition.PROPAGATION NESTED
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED;
4、TransactionDefinition.PROPAGATION MANDATORY
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:代表强制性)
5、TransactionDefinition.PROPAGATION SUPPORTS
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
6、TransactionDefinition.PROPAGATION NOT SUPPORTED
以非事务方式运行,如果当前存在事务,则把当前事务挂起。
7、TransactionDefinition.PROPAGATION NEVER
以非事务方式运行,如果当前存在事务,则抛出异常。
25.Spring事务中有哪几种事务隔离级别
1、TransactionDefinition.ISOLATION_DEFAULT 默认隔离级别
使用当前数据库的默认隔离级别, MySQL 默认采用的是可重复读 REPEATABLE_READ隔离级别。 oracle 默认采用的是读已提交 READ_COMMITTED 隔离级别;
2、TransactionDefinition.ISOLATION READ UNCOMMITTED 读未提交
最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读;
3、TransactionDefinition.ISOLATION READ_COMMITTED 读已提交
允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生;
4、TransactionDefinition.ISOLATION REPEATABLE READ可重复读
对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
5、TransactionDefinition.ISOLATION_SERIALIZABLE串行化
最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
26.Spring事务在什么情况下会失效
1、数据库不支持事务
Spring事务生效的前提是所连接的数据库要支持事务,如果底层的数据库都不支持事务,则Spring的事务肯定会失效。例如: 如果使用的数据库为 MySQL,并且选用了 MyISAM存储引擎,则 spring的事务就会失效。
2、事务方法未被Spring管理
如果事务方法所在的类没有加载到 Spring Ioc容器中,也就是说,事务方法所在的类没有被 Spring 管理,则 Spring 事务会失效。例如: ProductService 类上没有标注 @Service注解,Product 的实例没有加载到 Spring IoC 容器中,就会造成 updateProductstockCountById()方法的事务在Spring中失效。
3、方法没有被public修饰
如果事务所在的方法没有被 public 修饰,此时 Spring 的事务会失效,例如:虽然 Productservce 上标注] Service 注,时 updateProductstockCountById()方法上标注了@Transactional(propagation = Propagation.REQUIRES_NEW)注解。
但是,由于updateProductstockCountById()方法为内部的私有方法(使用 private修饰),那么此时 updateProductstockCountById()方法的事务在 Spring 中会失效。
4、同一类中方法调用
如果同一个类中的两个方法分别为A和B,方法A上没有添加事务注解,方法B上添加了 @Transactional 事务注解,方法A调用方法B,则方法B的事务会失效。例如:submitOrder()方法和 updateProductstockCountById() 方法都在 orderService 类中,submitOrder()方法上没有标注事务注解,updateProductstockCountById() 方法上标注了事务注解, submitOrder()方法调用了 updateProductstockCountById() 方法,此时,updateProductStockCountById()方法的事务在 Spring 中会失效。
5、未配置事务管理器
如果在项目中没有配置Spring的事务管理器,即使使用了 Spring 的事务管理功能,Spring的事务也不会生效。例如:没有在项目的配置类中配置如下代码。
6、方法的事务传播类型不支持事务
如果内部方法的事务传播类型为不支持事务的传播类型,则内部方法的事务在 Spring中会失效。例如:由于 updateProductstockCountById()方法的事务传播类型为 NOT_SUPPORTED,不支持事务,则 updateProductstockCountById()方法的事务会在 Spring 中失效。
7、不正确的异常捕获
不正确的捕获异常也会导致 Spring 的事务失效。
8、错误的标注异常类型
如果在@Transactional 注解中标注了错误的异常类型,则 spring 事务的回滚会失效。例如: 在 updateProductstockCountById() 方法中捕获了异常,并且在异常中抛出了 Exception类型的异常,此时, updateProductstockCountById() 方法事务的回滚会失效。
为何会失效呢?这是因为 Spring中对于默认回滚的事务异常类型为 RuntimeException,上述代码抛出的是Exception 异常。
默认情况下,Spring 事务中无法捕获到 Exception 异常,所以此时 updateProductstockCountById()方法事务的回滚会失效。
此时可以手动指定updateProductstockCountById()方法标注的事务异常类型。
27.谈谈对Spring MVC的理解
首先, MVC 模式 是模型( Mode )、视图( View 、控制器( Controller )的简写,其核心思想是通过将请求处理控制、业务逻辑、数据封装、数据显示等流程节点分离的思想来组织代码。
所以,MVC 是一种设计模式,而 spring MVC 是一款基于 MVC 设计模式思想实现的的 MVC 框架,属于Spring技术栈的一部分。 Spring MVC 可以帮助我们进行更简洁的 web 层的开发,并且它天生与 spring 框架集成,更利于架构的设计与搭建。
28.Spring MVC的工作原理(执行流程)
1、客户端 (浏览器)发送请求,统一由 DispatcherServlet 拦截处理请求;
2、DispatcherServlet根据请求信息调用 HandlerMapping 。HandlerMapping根据uri去匹配查找能处理的Handler(也就是我们定义的 Controller 控制器) ,并会将请求涉及到的拦截器和 Handler 一起封装;
3、DispatcherServlet 调用 HandlerAdapter 适配执行 Handler 。
4、Handler 完成对用户请求的处理后,会返一个 ModelAndView 模型视图对象给 DispatcherServlet 。 ModelAndview 中包含了数据模型以及相应的视图信息。 Model 是返回的数据对象,View 是 View 视图的逻辑名称。
5、 ViewResolver 会根据逻辑 View 名称查找并解析实际的 View 视图文件,并根据 DispaterServlet 返回的 Model 数据模型传给 View 视图文件,进行染执行,产生响应结果。
6、DispaterServlet 负责将响应结果,输出至客户端浏览器。
29.SpringMVC的核心组件有哪些
1、DispatcherServlet : 核心处理器,负责统一接收请求将请求分发至不同的控制器,并负责客户端响应;
2、HandlerMapping : 处理器映射器,根据 uri 去配查找能处理的 Handler ,并会将请求涉及到的拦截器和 Handler 一起封装。
3、HandlerAdapter : 处理器适配器,根据 HandlerMapping 找到的 Handler ,适配执行对应的 Handler;
4、Handler : 请求处理器,处理实际请求的处理器。
5、ViewResolver : 视图解析器,根据 Handler 返回的逻辑视图名称,解析并染真正的视图文件,并传递给 DispatcherServlet 响应至客户端