一 “集合”一章考点
1. HashMap的数据结构
HashMap是一个链表的数组
2. HashMap是如何处理Hash冲突的
(1)Hash冲突产生于put时,put时逻辑:
(a) 对key的hashCode()做hash,然后再计算index;
(b)如果没碰撞直接放到bucket里;
(c)如果碰撞了,以链表的形式存在buckets前面(1.8是放在buckets后
面)
(d)如果碰撞导致链表过长(大于等于TREEIFY_THRESHOLD),就把
链表转换成红黑树;
(e)如果节点已经存在就替换old value(保证key的唯一性)
(f)如果bucket满了(超过load factor*current capacity),就要resize。
(2)get时源码
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) return e.value;
3. HashMap什么地方线程不安全
是由hash冲突和扩容
hash冲突时:会形成链表,两个线程一起来,就只有一个保存成功
扩容:扩容需要把原来的数组写到一个新数组里面,然后在把新数
组赋值给table变量,最后只有一个线程能赋值成功,其它的
都被覆盖。
4. JDK1.8对HashMap做的优化
“由数组+链表”改为“数组+链表+红黑树”。当链表长度太长(默认超
过8)时,链表就转换为红黑树
5. HashTable和HashMap的区别
我太熟悉了
3 TreeMap以及TreeMap和HashMap的比较
(1)非线程安全的
(2)基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
(3)TreeMap适用于按自然顺序或自定义顺序遍历键(key);HashMap适用于在
Map中插入、删除和定位元素。
4.ConcurrentHashMap和HashMap、ConcurrentHashMap和HashTable
这个我也太熟悉了
5. Set 和 List区别
Set:无序不可重复
List:有序可重复
6. ArrayList为什么线程不安全
概括的说就是扩容时下标越界和赋值(添加新元素)时元素覆盖
详细解释(有空看,没空不看):
线程不安全的源码:
public boolean add(E e) { /** * 添加一个元素时,做了如下两步操作 * 1.判断列表的capacity容量是否足够,是否需要扩容 * 2.真正将元素放在列表的元素数组里面 */ ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
ArrayList的本质是一个Object数组,线程不安全发生在两个地方
ArrayList的add操作执行逻辑
(a)判断Object数组(elementData)容量是否足够
(b)在elementData对应位置上设置值
(1)扩容时下标越界(达到Object(elementData)数组最大下标时才扩容)
(a)列表大小为9,即size=9
(b)线程A开始进入add方法,这时它获取到size的值为9,调用
ensureCapacityInternal方法进行容量判断。
(c)线程B此时也进入add方法,它获取到size的值也为9,也开始调
用ensureCapacityInternal方法。
(c)线程A发现需求大小为10,而elementData的大小就为10,可以
容纳。于是它不再扩容,返回。
(d)线程B也发现需求大小为10,也可以容纳,返回。
(e)线程A开始进行设置值操作, elementData[size++] = e 操作。
此时size变为10。
(f)线程B也开始进行设置值操作,它尝试设置elementData[10] = e,
而elementData没有进行过扩容,它的下标最大为9。于是此时
会报出一个数组越界的异常ArrayIndexOutOfBoundsException.
(2)赋值时元素覆盖
elementData[size++] = e 设置值的操作同样会导致线程不安全。这不是
一个原子操作,它由以下两步组成:
第一步:elementData[size] = e;
第二步:size = size + 1;
在单线程执行这两条代码时没有任何问题,但是当多线程环境下执行时,
可能就会发生一个线程的值覆盖另一个线程添加的值,具体逻辑如下:
列表大小为0,即size=0
(a)线程A开始添加一个元素,值为A。此时它执行第一条操作,将A放
在了elementData下标为0的位置上。
(b)接着线程B刚好也要开始添加一个值为B的元素,且走到了第一步操
作。此时线程B获取到size的值依然为0,于是它将B也放在了
elementData下标为0的位置上。
(c)线程A开始将size的值增加为1
(d)线程B开始将size的值增加为2
详细请看文章:
https://blog.csdn.net/u012859681/article/details/78206494
7. Vector
线程安全的List
8. CopyOnWriteArrayList和Collections.synchronizedList()
CopyOnWriteArrayList和Collections.synchronizedList是实现线程安全的列表的
两种方式。两种实现方式分别针对不同情况有不同的性能表现,其中
CopyOnWriteArrayList的多线程写操作性能较差,而多线程的读操作性能较好。
Collections.synchronizedList的写操作性能比CopyOnWriteArrayList在多线程操
作的写操作好很多,而读操作因为是采用了synchronized关键字的方式,其读
操作性能并不如CopyOnWriteArrayList。因此在不同的应用场景下,应该选择不
同的多线程安全实现类。
CopyOnWriteArrayList是java.util.concurrent包中的一个List的实现类。
CopyOnWrite的意思是在写时拷贝,也就是如果需要对CopyOnWriteArrayList
的内容进行改变,首先会拷贝一份新的List并且在新的List上进行修改,最后将原
List的引用指向新的List。CopyOnWriteArrayList可以线程安全的遍历
1. 线程和进程的区别与联系
答:进程是资源分配的最小单位;线程是程序执行的最小单位;
一个进程可以有多个线程,如果一个进程只有一个线程,那
么该进程是单线程的进程。
2. Lock和Sychronized的区别
答:等待可中断、可实现公平锁、可以绑定多个条件(面试时不要答)
3. ReenTrantLock 原理
脑补一遍
4. JDK1.6对sychronized做的优化
太长了不写了
5. volatile
可保证可见性、有序性但是不能保证原子性
6. CAS AQS
7. 公平锁和非公平锁
8. 线程池
keepAliveTime:空闲的线程保留的时间。
TimeUnit:空闲线程的保留时间单位。
上面两个粘这加深记忆
直接丢弃(DiscardPolicy)
丢弃队列中最老的任务(DiscardOldestPolicy)。
默认,直接抛异常(AbortPolicy)
将任务分给调用线程来执行(CallerRunsPolicy)。
9. ThreadLocal
1. 说明一下什么是IOC/DI
IOC是控制反转;DI是依赖注入
(1)IOC,控制反转
-- 正传和反转
正转,就是传统应用程序是由我们自己在对象中主动控
制去直接获取依赖对象。
反转:就是由容器来帮忙创建及注入依赖对象。
-- 谁控制谁?控制什么
由IOC容器控制所依赖的对象。
传统的应用中程序是通过new主动创建依赖对象,而IoC是有专门
一个容器来创建这些对象,所以是由IOC容器控制所依赖的对象。
(2)DI,依赖注入
-- DI的由来
由于控制反转概念比较含糊(可能只是理解为容器控制对象这一
个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物
Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,
“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
-- 谁依赖谁谁?为什么要依赖?
应用程序依赖IOC容器,因为应用程序需要的IOC容器提供需要的外部
资源。
-- 谁注入谁?注入什么?
IOC容器注入应用古程序的某个对象,注入的是应用程序某个对象需要
的外部资源
2. 依赖注入和控制反转是同一概念吗?
答:不是同一概念,是同一事物的不同角度的描述,控制反转是从IOC/DI容
器角度来说;依赖注入是从应用程序角度来说。
面试的时候可以答就是一个东西。
3. IOC/DI的优点
答:IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,
它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由
我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测
试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由
容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便
测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵
活。
2. Spring Aop的原理
Spring Aop的原理使用的时代理模式
代理模式分为:
(1)静态代理
(2)动态代理
(a)JDK动态代理
(b)cglib动态代理代理
动态代理和静态代理的区别:
静态代理是在编译时就确认了代理类
动态代理是在运行时由反射确认代理类
JDK动态代理和cglib代理的区别:
JDK动态代理只能对实现了接口的类生成代理,而不能针对类;CGLIB
是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
(继承)当Bean实现接口时,Spring就会用JDK的动态代理;当Bean没
有实现接口时,Spring使用CGlib是实现
3. Aop的优点
(1)关注点在需要增加或删除这些共性功能的时候不需对目标模块进行修改,
实现了快速插拔
(2)使得系统架构更优良,分而治之,关注点只需要关注自身要实现的共性
的功能,服务模块只需要关注自身的核心功能,这样设计胜过共性功能
糅杂进服务模块。
4. Aop术语
(1)关注点:又名“横切关注点”,是我们关注的共性的功能。比如用户日志
记录、用户的验证
(2)切面:横切关注点被模块化为特殊的类,这些类称为切面。
(3)通知:切面的工作被称为通知。其实就是指拦截到连接点之后要执行
的代码
Before——在方法调用之前调用通知。
After——在方法完成之后调用通知,无论方法执行成功与否。
After-returning——在方法执行成功之后调用通知。
After-throwing——在方法抛出异常后进行通知。
Around——通知包裹了被通知的方法,在被通知的方法调用之
前和调用之后执行自定义的行为。
(4)连接点:一个类或一段程序代码拥有一些具有边界性质的特定点,这
些点中的特定点就称为“连接点”。如类开始初始化前、类初始
化后、类某个方法调用前、调用后、方法抛出异常后。
通俗的说就是“目标对象或者代理对象之中的方法”
(5)切入点:对连接点进行拦截的定义。举个例子,连接点相当于数据库
中的记录,而切点相当于查询条件。切点和连接点不是一对
一的关系,一个切点可以匹配多个连接点。
5. 数据库事务
(1)事务特性
A:原子性
C:一致性
I:隔离性
D:持久性
张三给李四转账100元,需要先重张三的账户上减去100元,在给李四
的账户上增加100元,如果张三减去100失败那么整个事物就回滚,这
就是原子性的体现;假设张三李四的账户在转账前都是1000元,那么
转账后张三账户为900元,李四账户为1100元,这就是一致性的体现。
(2)事务的隔离级别
事务的隔离级别由低到高分别是:
READ UNCOMMITTED 幻读、不可重复读和脏读都允许。
READ COMMITTED 允许幻读、不可重复读,不允许脏读。
REPEATABLE READ 允许幻读,不允许不可重复读和脏读。
SERIALIZABLE 幻读、不可重复读和脏读都不允许。
幻读
数据发生新增。第一个事务对一个表中的所有数据进行
了修改,同时,第二个事务向这个表中插入一行新数据。
那么,以后就会发生操作第一个事务的用户发现表中还
有没有修改的数据行,就好象发生了幻觉一样。
不可重复读:
数据发生修改由于一个事务的修改导致另外一个事务两
次读到的数据不一致。如在一个事务内,多次读同一数
据。在这个事务还没有结束时,另外一个事务也访问该
同一数据。那么,在第一个事务中的两次读数据之间,
由于第二个事务的修改,那么第一个事务两次读到的的
数据可能是不一样的。
脏读
读到了另外一个事务未提交的数据。如当一个事务正在
访问数据,并且对数据进行了修改,而这种修改还没有
提交到数据库中,这 时,另外一个事务也访问这个数
据,然后使用了这个数据。
5. Spring 事务的原理
有空在看
6. Spring事务的传播
REQUIRED(默认)
业务方法需要在一个容器里运行。如果方法运行时,已经处在一
个事务中,那么加入到这个事务,否则自己新建一个新的事务(
默认,和SUPPORTS一起记)
SUPPORTS
该方法在某个事务范围内被调用,则方法成为该事务的一部分。
如果方法在该事务范围外被调用,该方法就在没有事务的环境
下执行(和默认分一类吧,暂叫它默认2吧)。
REQUIRESNEW
总会发起一个新得事务。不管是否存在事务,该方法总会为自
己发起一个新的事务。如果方法已经运行在一个事务中,则原
有事务挂起,新的事务被创建(新事务,零碎没组)。
NOT_SUPPORTED
总是没有事务。如果方法没有关联到一个事务,容器不
会为他开启事务,如果方法在一个事务中被调用,该事务会被
挂起,调用结束后,原先的事务会恢复执行(不需要事务,零
碎没组)。
MANDATORY
必须要有事务
该方法只能在一个已经存在的事务中执行,业务方法不能发起
自己的事务。如果在没有事务的环境下被调用,容器抛出例外
(必须要在有事务的环境中执行,和NEVER一起记)。
NEVER
必须没有事务
该方法绝对不能在事务范围内执行。如果在就抛例外。只有该
方法没有关联到任何事务,才正常执行(必须要在没有有事务
的环境中执行)。
NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中。如果
没有活动事务,则按REQUIRED属性执行。它使用了一个单独
的事务,这个事务拥有多个可以回滚的保存点。内部事务的回
滚不会对外部事务造成影响。它只对
DataSourceTransactionManager事务管理器起效。
7. Spring常用标签
(1)@Controller、@Service、@Respository,分别是Controller、
Service、Dao的注解。
(2)@Component
(3)@Resource和@Autowired
@Resource和@Autowired功能相同,区别是@Resource是按照name
注入,而@Autowired是按照type注入。
8. Spring bean的生命周期(创建、调用、销毁,这里有一个流程,我没有理解,只是记忆一下),
(1)实例化bean对象(通过构造方法或者工厂方法)
(2)设置对象属性(setter等)(依赖注入)
(3)检查Aware接口,设置相关依赖。如果Bean实现了BeanNameAware接
口,spring将bean的id传给setBeanName()方法;如果Bean实现了
BeanFactoryAware接口,spring将调用setBeanFactory方法,将
BeanFactory实例传进来。
(4)将Bean实例传递给Bean的前置处理器的
postProcessBeforeInitialization(Object bean, String beanname)方法
(5)调用Bean的初始化方法。(初始化bean有两种方式,在配置文件中通过
指定init-method属性来完成和实现
org.springframwork.beans.factory.InitializingBean接口。图上有画)
(6)将Bean实例传递给Bean的后置处理器的
postProcessAfterInitialization(Object bean, String beanname)方法使用
Bean。
(7)使用。此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻
留在应用上下文中,直到该应用上下文被销毁。
(8)容器关闭之前,调用Bean的销毁方法(bean的销毁方法有两种:使用
配置文件指定的destroy-method属性和实现
org.springframwork.bean.factory.DisposeableBean接口。图上有画)
8. Bean的作用域
singleton、prototype、request、session、global session
9. Bean注入方式
(1)setter注入
(2)构造器注入
(3)静态工厂方法注入
(4)实例工厂方法注入
10. Spring MVC的处理请求的流程
(1)客户端请求提交到DispatcherServlet
(2)由DispatcherServlet控制器查询一个或多个HandlerMapping,找到
处理请求的Controller
(3)DispatcherServlet将请求提交到Controller
(4)Controller调用业务逻辑处理后,返回ModelAndView
(5)DispatcherServlet查询一个或多个ViewResoler视图解析器,找到
ModelAndView指定的视图
(6)视图负责将结果显示到客户端
9. BeanFactory 接口和 ApplicationContext 接口有什么区别
有空在看
(11)Spring Quartz和Spring Task
有空看,不重要,重要的了解是分布式的,比如当当的
四 “缓存”一章考点
1. 说明一下什么是IOC/DI
IOC是控制反转;DI是依赖注入
(1)IOC,控制反转
-- 正传和反转
正转,就是传统应用程序是由我们自己在对象中主动控
制去直接获取依赖对象。
反转:就是由容器来帮忙创建及注入依赖对象。
-- 谁控制谁?控制什么
由IOC容器控制所依赖的对象。
传统的应用中程序是通过new主动创建依赖对象,而IoC是有专门
一个容器来创建这些对象,所以是由IOC容器控制所依赖的对象。
(2)DI,依赖注入
-- DI的由来
由于控制反转概念比较含糊(可能只是理解为容器控制对象这一
个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物
Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,
“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
-- 谁依赖谁谁?为什么要依赖?
应用程序依赖IOC容器,因为应用程序需要的IOC容器提供需要的外部
资源。
-- 谁注入谁?注入什么?
IOC容器注入应用古程序的某个对象,注入的是应用程序某个对象需要
的外部资源
2. 依赖注入和控制反转是同一概念吗?
答:不是同一概念,是同一事物的不同角度的描述,控制反转是从IOC/DI容
器角度来说;依赖注入是从应用程序角度来说。
面试的时候可以答就是一个东西。
3. IOC/DI的优点
答:IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,
它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由
我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测
试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由
容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便
测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵
活。
2. Spring Aop的原理
Spring Aop的原理使用的时代理模式
代理模式分为:
(1)静态代理
(2)动态代理
(a)JDK动态代理
(b)cglib动态代理代理
动态代理和静态代理的区别:
静态代理是在编译时就确认了代理类
动态代理是在运行时由反射确认代理类
JDK动态代理和cglib代理的区别:
JDK动态代理只能对实现了接口的类生成代理,而不能针对类;CGLIB
是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
(继承)当Bean实现接口时,Spring就会用JDK的动态代理;当Bean没
有实现接口时,Spring使用CGlib是实现
3. Aop的优点
(1)关注点在需要增加或删除这些共性功能的时候不需对目标模块进行修改,
实现了快速插拔
(2)使得系统架构更优良,分而治之,关注点只需要关注自身要实现的共性
的功能,服务模块只需要关注自身的核心功能,这样设计胜过共性功能
糅杂进服务模块。
4. Aop术语
(1)关注点:又名“横切关注点”,是我们关注的共性的功能。比如用户日志
记录、用户的验证
(2)切面:横切关注点被模块化为特殊的类,这些类称为切面。
(3)通知:切面的工作被称为通知。其实就是指拦截到连接点之后要执行
的代码
Before——在方法调用之前调用通知。
After——在方法完成之后调用通知,无论方法执行成功与否。
After-returning——在方法执行成功之后调用通知。
After-throwing——在方法抛出异常后进行通知。
Around——通知包裹了被通知的方法,在被通知的方法调用之
前和调用之后执行自定义的行为。
(4)连接点:一个类或一段程序代码拥有一些具有边界性质的特定点,这
些点中的特定点就称为“连接点”。如类开始初始化前、类初始
化后、类某个方法调用前、调用后、方法抛出异常后。
通俗的说就是“目标对象或者代理对象之中的方法”
(5)切入点:对连接点进行拦截的定义。举个例子,连接点相当于数据库
中的记录,而切点相当于查询条件。切点和连接点不是一对
一的关系,一个切点可以匹配多个连接点。
5. 数据库事务
(1)事务特性
A:原子性
C:一致性
I:隔离性
D:持久性
张三给李四转账100元,需要先重张三的账户上减去100元,在给李四
的账户上增加100元,如果张三减去100失败那么整个事物就回滚,这
就是原子性的体现;假设张三李四的账户在转账前都是1000元,那么
转账后张三账户为900元,李四账户为1100元,这就是一致性的体现。
(2)事务的隔离级别
事务的隔离级别由低到高分别是:
READ UNCOMMITTED 幻读、不可重复读和脏读都允许。
READ COMMITTED 允许幻读、不可重复读,不允许脏读。
REPEATABLE READ 允许幻读,不允许不可重复读和脏读。
SERIALIZABLE 幻读、不可重复读和脏读都不允许。
幻读
数据发生新增。第一个事务对一个表中的所有数据进行
了修改,同时,第二个事务向这个表中插入一行新数据。
那么,以后就会发生操作第一个事务的用户发现表中还
有没有修改的数据行,就好象发生了幻觉一样。
不可重复读:
数据发生修改由于一个事务的修改导致另外一个事务两
次读到的数据不一致。如在一个事务内,多次读同一数
据。在这个事务还没有结束时,另外一个事务也访问该
同一数据。那么,在第一个事务中的两次读数据之间,
由于第二个事务的修改,那么第一个事务两次读到的的
数据可能是不一样的。
脏读
读到了另外一个事务未提交的数据。如当一个事务正在
访问数据,并且对数据进行了修改,而这种修改还没有
提交到数据库中,这 时,另外一个事务也访问这个数
据,然后使用了这个数据。
5. Spring 事务的原理
有空在看
6. Spring事务的传播
REQUIRED(默认)
业务方法需要在一个容器里运行。如果方法运行时,已经处在一
个事务中,那么加入到这个事务,否则自己新建一个新的事务(
默认,和SUPPORTS一起记)
SUPPORTS
该方法在某个事务范围内被调用,则方法成为该事务的一部分。
如果方法在该事务范围外被调用,该方法就在没有事务的环境
下执行(和默认分一类吧,暂叫它默认2吧)。
REQUIRESNEW
总会发起一个新得事务。不管是否存在事务,该方法总会为自
己发起一个新的事务。如果方法已经运行在一个事务中,则原
有事务挂起,新的事务被创建(新事务,零碎没组)。
NOT_SUPPORTED
总是没有事务。如果方法没有关联到一个事务,容器不
会为他开启事务,如果方法在一个事务中被调用,该事务会被
挂起,调用结束后,原先的事务会恢复执行(不需要事务,零
碎没组)。
MANDATORY
必须要有事务
该方法只能在一个已经存在的事务中执行,业务方法不能发起
自己的事务。如果在没有事务的环境下被调用,容器抛出例外
(必须要在有事务的环境中执行,和NEVER一起记)。
NEVER
必须没有事务
该方法绝对不能在事务范围内执行。如果在就抛例外。只有该
方法没有关联到任何事务,才正常执行(必须要在没有有事务
的环境中执行)。
NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中。如果
没有活动事务,则按REQUIRED属性执行。它使用了一个单独
的事务,这个事务拥有多个可以回滚的保存点。内部事务的回
滚不会对外部事务造成影响。它只对
DataSourceTransactionManager事务管理器起效。
7. Spring常用标签
(1)@Controller、@Service、@Respository,分别是Controller、
Service、Dao的注解。
(2)@Component
(3)@Resource和@Autowired
@Resource和@Autowired功能相同,区别是@Resource是按照name
注入,而@Autowired是按照type注入。
8. Spring bean的生命周期(创建、调用、销毁,这里有一个流程,我没有理解,只是记忆一下),
(1)实例化bean对象(通过构造方法或者工厂方法)
(2)设置对象属性(setter等)(依赖注入)
(3)检查Aware接口,设置相关依赖。如果Bean实现了BeanNameAware接
口,spring将bean的id传给setBeanName()方法;如果Bean实现了
BeanFactoryAware接口,spring将调用setBeanFactory方法,将
BeanFactory实例传进来。
(4)将Bean实例传递给Bean的前置处理器的
postProcessBeforeInitialization(Object bean, String beanname)方法
(5)调用Bean的初始化方法。(初始化bean有两种方式,在配置文件中通过
指定init-method属性来完成和实现
org.springframwork.beans.factory.InitializingBean接口。图上有画)
(6)将Bean实例传递给Bean的后置处理器的
postProcessAfterInitialization(Object bean, String beanname)方法使用
Bean。
(7)使用。此时bean已经准备就绪,可以被应用程序使用了,他们将一直驻
留在应用上下文中,直到该应用上下文被销毁。
(8)容器关闭之前,调用Bean的销毁方法(bean的销毁方法有两种:使用
配置文件指定的destroy-method属性和实现
org.springframwork.bean.factory.DisposeableBean接口。图上有画)
8. Bean的作用域
singleton、prototype、request、session、global session
9. Bean注入方式
(1)setter注入
(2)构造器注入
(3)静态工厂方法注入
(4)实例工厂方法注入
10. Spring MVC的处理请求的流程
(1)客户端请求提交到DispatcherServlet
(2)由DispatcherServlet控制器查询一个或多个HandlerMapping,找到
处理请求的Controller
(3)DispatcherServlet将请求提交到Controller
(4)Controller调用业务逻辑处理后,返回ModelAndView
(5)DispatcherServlet查询一个或多个ViewResoler视图解析器,找到
ModelAndView指定的视图
(6)视图负责将结果显示到客户端
9. BeanFactory 接口和 ApplicationContext 接口有什么区别
有空在看
(11)Spring Quartz和Spring Task
有空看,不重要,重要的了解是分布式的,比如当当的
原文:https://www.cnblogs.com/jialanshun/p/10574228.html