JAVA学习
2023-01-30 11:28:43 1 举报
AI智能生成
登录查看完整内容
java学习资料
作者其他创作
大纲/内容
概念
关系型数据库中的数据库(DataBase),等价于ES中的索引(Index)
一个数据库下面有N张表(Table),等价于1个索引Index下面有N多类型(Type)
在一个关系型数据库里面,schema定义了表、每个表的字段,还有表和字段之间的关系。 与之对应的,在ES中:Mapping定义索引下的Type的字段处理规则,即索引如何建立、索引类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等。
在数据库中的增insert、删delete、改update、查search操作等价于ES中的增PUT/POST、删Delete、改_update、查GET.
与关系型数据库比较
实时性好,
随着数据量的增加sorl效率降低,ES不变
与solr相比
例如:id为1,3,4的几个的name都是‘张三’,那么根据张三这个名称可以找到【1,3,4】这个数据,进而找到对应的document.
简单地说就是根据value去找key
子主题 2
倒排索引
子主题 3
子主题 4
索引
ElasticSearch
一般用于聊天
接收到客户端消息时触发的方法
onOpen
根据连接信息进行相关的业务逻辑,调用sendMessage方法
onMessage
关闭连接时调用的
onClose
发生错误时触发的方法
onError
sendMessage
MapUtil
websocket
1个字节8位
1个字节
byte
2个字节
short
char
4个字节
int
float
8个字节
long
double
boolean
基本数据类型
JAVA反射机制是在运行状态中,对于任意一个类。都能都知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称之为java语言的反射机制
机制
对象.getClass
类.class
class.forName()
获取class对象的三种方法
反射
java基础
实现:数组+链表
线程不安全
高:可以降低hash表所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的操作
低:会提高查询数据的性能,但会增加hash表所占用的内存开销
极限负载:0.75
hash冲突
扩容代码(先扩容再赋值):
1.7
实现:数组+链表/红黑树
在jdk1.8中,如果链表长度大于8且节点数组长度大于64的时候,就把链表下所有的节点转为红黑树。
扩容代码(先赋值再扩容):
树化过程:先将单向链表转成双向链表,然后将双向链表转成红黑树
1.8
1.7和1.8扩容成环问题
hashMap
实现方式:Segment + HashEntry
实现方式:Node + CAS + Synchronized
concurrentHashMap
hashmap与concurrentHashMap
hashtable
各个集合之间的区别
存储是有序的,参考文章https://www.cnblogs.com/lyhc/p/10743550.html
LinkedHashMap
HashMap
TreeMap
Map
数组
ArrayList
双向链表
LinkedList
与arrayList类似,线程安全的
Vector
list
hash表结构
HashSet
红黑树结构
TreeSet
Set(元素不重复)
Queue
Collection
集合类
基础知识
隔离的虚拟的容器,类似虚拟机但是比虚拟机更轻
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq:management
因为docker是一个容器,所以镜像启动时需要指定端口映射
docker pull(从网上拉去镜像)
docker images(查看下面有大写镜像)
docker ps (查看运行的容器)
使用exit退出来
docker exec -it 7d9750ee6e44 bash (进入容器内部)
docker stop 容器Id :停止docker
一些命令
参考博客:https://blog.csdn.net/q610376681/article/details/90483576
docker
子主题 1
分布式事务
唯一id的实现方式
基于表记录
乐观锁
悲观锁
基于数据库
思路:在redis中设置一个值表示加了锁,然后释放锁的时候就把这个key删除。
使用SET key value NX PX milliseconds 命令
分布式锁的实现还需要考虑redis集群部署的问题
根据key获取锁对象,加锁并设置过期时间,业务流程完成后释放锁。
redission
获取当前时间戳
client通过获取所有能获取的锁后的时间减去第一步的时间,这个时间差要小于TTL时间并且至少有3个redis实例成功获取锁,才算真正的获取锁成功
如果成功获取锁,则锁的真正有效时间是 TTL减去第三步的时间差 的时间
.如果客户端由于某些原因获取锁失败,便会开始解锁所有redis实例;因为可能已经获取了小于3个锁,必须释放,否则影响其他client获取锁
redlock原理
redis分布式锁
如果锁空间的根节点不存在,首先创建Znode根节点。
客户端如果需要占用锁,则在根节点下创建临时的且有序的子节点。
客户端如果需要占用锁,还需要判断,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点。如果是则认为获得锁,否则监听前一个Znode子节点变更消息,获得子节点变更通知后重复此步骤直至获得锁;
获取锁后,开始处理业务流程。完成业务流程后,删除对应的子节点,完成释放锁的工作。以便后面的节点获得分布式锁。
分布式锁算法流程
curator
zookeeper
分布式锁
dubbo
里面集成了哪些东西
注册中心:Eureka(还有consul和zookeeper)
负载均衡::Ribbon
容错处理:Hystrix
微服务网关:Zuul
springcloud
分布式
简单的算法
FanOut Exchange
Direct Exchange
Topic Exchange
一般用不到
Header Exchange/Default Exchange
Exchange
配置文件
ConfirmCallback
ReturnCallback
消息发送确认
ack
重发
拒绝(消息不被退回队列,进入死信队列中)
unack
消息接收确认
消息确认
死信队列和延时队列
普通集群
镜像集群
高可用性
消息丢失
重复消费
大量消息堆积
常见问题
RabbitMQ
堆
虚拟机栈
本地方法栈
程序计数器
常量池
java内存模型
效率不高
标记清除后容易产生空间碎片,分配较大的对象时无法找到连续的空间进行存储,所以不得已还得进行一次gc
标记出所有需要回收的对象,标记完统一回收所有被标记的对象
标记-清除算法
首先也是进行标记,标记过后让所有对象向一端移动,直接清理掉边界以外的内存,不存在空间碎片
标记整理算法(老年代)
将内存分成两块,每次只是用一块,当一块用完后,将还存活的对象存储到另一块中,然后把一使用过的内存空间清理掉。
在新生代中一般用E区和一个S区作为存储空间,另一个S区作为收集还存活的对象,当另一个S区没有足够空间时,可以通过担保机制将这些对象分配到老年代。
复制算法(新生代)
收集算法
单线程收集器,收集时必须停止其他线程。
优点:简单高效,对于单个CPU环境还说收集效率高。
Serial
Serial的多线程版本,第一款真正意义上的并发收集器
只有它可以和CMS共同工作
ParNew(新生代)
控制最大垃圾收集停顿时间参数-XX:MaxGCPauseMillis以及吞吐量大小参数-XX:GCTimeRatio
自适应调节策略
Parallel Scavenage(新生代)
一般与Parallel Scavenage一起使用
适用于注重吞吐量以及CPU敏感的场合
parallel Old(老年代)
获取最短回收停顿时间为目标的收集器
初始标记:标记一下GC roots能关联到的对象,速度很快(仍需要停顿)
并发标记:就是进行GC Roots Tracing(其实就是从GC Roots开始找到它能引用的所有其它对象)
修正并发标记期间因用户程序继续动作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
重新标记
并发清除:除掉将要回收的对象
过程
对CPU资源非常敏感
浮动垃圾:由于在并发清理过程中,用户线程还在执行,所以会随时产生新的垃圾,这一部分垃圾无法在本次清理过程中清理掉。
无法处理浮动垃圾
因为整理时候是无法并发的,所以停顿时间会增长。
解决方法
由于是标记-清除算法,所以会产生空间碎片。
缺点
CMS(老年代)原理:标记-清除
并行与并发
分代收集
空间整合
可预测停顿
特点
初始标记
并发标记
最终标记
筛选回收
G1
垃圾收集器
主要针对与吞吐量以及CPU资源敏感
默认在E区分配
-XX:PretenureSizeThreshold参数,令大于这个值的对象直接进老年代
大对象直接进老年代
长期存活的对象直接进老年代
空间分配担保
内存分配
Minor GC:新生代发生的垃圾收集动作
Full GC:老年代发生的垃圾收集动作
回收策略
内存分配与回收策略
jps
jstat
jinfo
jmap
jhat
jstack
常用命令
JConsole
BTrace
VisuallVM
可视化工具
性能监控与故障处理
调优案例
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验/转换/解析和初始化,最终形成可以被虚拟机直接使用的Java类型
通过一个类的全限定名获取定义此类的二进制字节流
将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
在内存中生成一个代表这个类的class对象,作为方法区这个类的各种数据访问入口
做三件事
数组类本身不通过类加载器创建,它是由Java虚拟机直接创建。但是数组类的元素类型最终是要靠类加载器去创建
数组类和非数组类的加载
加载
class文件可以通过任意文件产生
为了确保class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害到虚拟机自身的安全
目的
文件格式验证
元数据验证
字节码验证
符号引用验证
几种验证动作
对于虚拟机来说验证阶段是一个非常重要但是不一定必要的阶段。如果可以确保自己的代码没有问题可以使用-Xverify:one关闭验证阶段。
验证
这里说的内存分配仅包括类变量(被static修饰的变量),不包括实例变量,实例对象将会在对象实例化时随着对象一起分配到java堆中
正式为类变量分配内存并设置类变量初始值的阶段,这些变量所使用的内存将在方法区中进行分配。
设置初始值,并不会直接赋值,一般为零值
准备
以一组符号来描述所引用的目标,符号可以是任何形式的字面变量,只要使用时能无歧义的定位到目标即可
符号引用
是直接指向目标指针、相对偏移量或者句柄
直接引用
将符号引用替换成直接引用的过程
解析(可以在初始化之后开始)
连接
new 关键字实例化对象的时候、读取或设置一个类的静态字段以及调用一个类的静态方法的时候
使用反射的时候
初始化一个类时,其父类也必须初始化
虚拟机启动时,需要指定一个需要执行的主类,这个主类需要初始化
子主题 5
5种情况必须进行初始化
初始化
使用
卸载
类加载过程
启动类加载器
扩展类加载器
应用类加载器
类型
原理
破坏双亲委派
双亲委派
类加载器
类加载
JVM常用调优参数
JVM
单线程,线程安全
数据存在内存中,读写速度快(10W QPS)
支持多数据类型
支持数据持久化
主从/哨兵(高可用)
发布订阅(消息中间件)
优点
基本定义
是一种 动态字符串,这意味着使用者可以修改,它的底层实现有点类似于 Java 中的 ArrayList,有一个字符数组
String
相当于 Java 语言中的 LinkedList
list(双向链表)
类似hashmap中的key-value形式
hash
不重复的集合
sets
有序的不重复的集合
实现方式:跳表
sorted set
内存空间不均匀
容易导致超时阻塞
迁移困难
bigKey危害(主要还是太大,导致各方面的阻塞问题)
基础数据结构
redisTemplate.opsForSet()
redisTemplate.opsForHash()
redisTemplate.opsForList()
redisTemplate.opsForValue()
RedisTemplate 来使用
Spring Cache 集成 Redis(也就是注解的方式)后面看一下
redis缓存使用
快照形式是直接把内存中的数据保存到一个 dump 的文件中,定时保存,保存策略。
如何持久化的
定时备份数据,数据有可能会有缺失
RDB(默认)
把所有的对 Redis 的服务器进行修改的命令都存到一个文件里,命令的集合。
持久化
全程持久化
开启参数:appendonly yes
AOF
AOF的文件体积通常大于RDB的文件体积
AOF可以实时的但是这样巨大的写入会降低redis的性能
可以同时使用
当 Redis 重启的时候,它会优先使用 AOF 文件来还原数据集,因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。
两者的优缺点
定义:
设置热点数据永不过期,或者加上互斥锁就搞定了。
加上互斥锁
处理方法
缓存击穿
定义
接口层增加校验(不合理的数据进行拦截)
内部原理
采用布隆过滤器
缓存穿透
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。
设置热点数据永远不过期。
缓存雪崩
缓存击穿和缓存雪崩类似:缓存雪崩大量key缓存击穿针对一个key大量并发
缓存雪崩、缓存击穿和缓存穿透
为什么是单线程的还这么快
memcache不能持久化
memcache支持的数据类型比较简单
底层实现方式以及与客户端之间通信的应用协议不一样。
Memcache的区别
使用缓存的问题:与数据库不一致问题
allkeys-random: 所有key通用; 随机删除一部分 key。
volatile-random: 只限于设置了 expire 的部分; 随机删除一部分 key。
淘汰策略
建立连接为数据同步做准备
连接建立阶段
2.8以前发送sync命令,请求同步数据(全量的)2.8以后发送psync命令同步数据,可能是全量也可能时部分的。
从节点主动请求全量复制
从节点请求部分复制,但是主节点认为无法进行部分复制
两种情况
接收到命令--执行bgsave--生成RBD文件--将文件传给从节点
全量复制
用于处理网络中断时的数据同步。
复制偏移量(就是判断那一部分数据该同步)
复制积压缓冲区
服务器运行ID(runid)
依赖于
部分复制
psync
sync
参考博客:https://www.cnblogs.com/kismetv/p/9236731.html
数据同步阶段
发送写命令,主从节点还维持着心跳机制
命令传播阶段
三个阶段
延迟与不一致问题
数据过期问题
故障切换问题(使用哨兵进行节点切换)
读写分离有可能出现的问题
主从复制
核心功能是主节点的自动故障转移
监控(Monitoring):哨兵会不断地检查主节点和从节点是否运作正常。
自动故障转移
配置提供者
通知(Notification):哨兵可以将故障转移的结果发送给客户端。
功能
哨兵模式
集群
Redis
start与run的区别:start是创建一个线程并执行run方法,run的话时在当前线程中调用run方法,并执行其中的逻辑,并不会创建另一个线程
start()
直接终止线程并释放锁,会破环对象的一致性(已被废弃)
stop()
通知线程中断,但不会立即中断,只是个线程标识而已,可以根据下面的方法判断,并写出对应的中断逻辑。
Thread.interrupt()
判断线程是否中断,可以根据返回的状态写出中断逻辑。
Thread.isInterrupt()
判断是否被中断,并清除当前中断状态
Thread.interrupted()
interrupt()
使当前线程在这个对象上等待,会一直等待到其他线程调用了notify方法(可以利用同一个对象实现多线程之间的通信)
wait():object中的方法
唤醒当前对象的一个线程,如果有多个线程等待,随机唤醒一个。notifyAll()可以唤醒全部
notify():object中的方法
suspend导致线程暂停的同时,还不会释放任何锁资源,直到该线程进行了resume操作(方法已经废弃)
suspend()和resume():挂起和继续执行
阻塞当前线程,直至调用join的线程结束后,主线程才会继续执行。参数还可以加上最大等待时间。
join()
当前线程让出CPU然后再一起争夺资源
yeild()
当守护的线程不执行时,该线程会自动结束,设置是否是守护线程必须在start()方法之前。
守护线程
基本的方法
继承thread类
实现runnable()接口
实现callable()接口
创建线程方法
主要用来保证变量的可见性,任意一线程对某一变量修改后,其他线程都会看到。但是有时也无法保证一些复合操作的原子性。
volatile
有着显示的加锁过程,对逻辑控制的灵活性远远好于synchronized。
原子状态,使用CAS操作来存储当前锁的状态,判断所是否已经被别的线程持有。
等待队列。所有未获得锁的线程,会进入等待队列进行等待,待有线程释放锁后,系统就能唤醒一个线程继续工作。
阻塞原语,用来挂起和恢复线程。
实现主要包括三个因素
lock():获得锁
tryLock():尝试获得锁,返回true或false
tryLocak(时间参数):在给定时间内获取锁
unlock():释放锁
几种方法
可重入锁
与Object中的wait和notify()方法大致相同
lock.newCondition()生成
await():当前线程等待,同时释放锁
singal():唤醒
方法
condition条件
一般来说,如果加锁的话,只允许一个线程访问,不需要再用其他锁,本身就是个锁
acquire():尝试获得一个准入的许可
release():释放信号量
信号量(Semaphore):允许多个线程同时访问
两个锁,读时用读锁,写时用写锁,读的时候不阻塞,
读写锁
设置一个计树个数,当消耗完后,后面的逻辑才会执行。
主线程再CountDownLatch上等待,当所有检查任务都执行完后才能继续执行。
countDown():计数减一
await():等待计数归零
使用场景:
倒计时器(CountDownLatch)
循环栅栏
JDK并发包
Executor--ExecutorService--AbstarctExecutorService--ThreadPoolExecutor
corePoolSize
maxumumPoolSize
keepAliveTime
unit
没有容量,不会保存任务,当进程数量达到最大时执行拒绝策略
newCacheThreadPool()
直接提交的队列(SynchronousQueue)
队列的构造函数必须带有一个最大容量的参数,当队列的容量到达最大参数时,在总线程数不大于max的情况下继续创建线程,若大于max了,则执行拒绝策略
有界任务队列(ArrayBlockingQueue)
与有界队列不同的是,队列没有容量限制,不存在入队列失败情况,直至内存耗尽。
newFixedThreadPool()newSingleThreadExecutor()
无界任务队列(LinkedBlockingQueue)
是一个特殊的无界队列,只不过可以根据线程的优先级执行任务
优先任务队列(PriorityBlockingQueue)
workQueue
线程工厂用默认的就行
ThreadFactory
一般默认的处理策略
AbortPolicy:直接抛出异常
DiscardOledestPolicy:丢弃一个即将被执行的任务,并尝试再次提交当前任务。
DiscardPolicy:丢弃无法处理的任务,不做任何处理
CallerRunsPolicy:只要线程未关闭就会继续执行被丢弃的任务,并不会真的丢弃任务。
handler(拒绝策略)
创建线程池的参数
返回固定数量的线程池,该线程池的线程数量始终不变。
创建参数
无界任务队列
abortPolicy:直接抛出异常的拒绝策略
newFixedThreadPool()
返回一个只有一个线程的线程池
newSingleThreadExecutor()
可以根据实际情况调整数量的线程池,coresize为0,maxsize为无穷大的
直接提交的队列
newSingleThreadScheduledExecutor()
new DelayedWorkQueue()优先级队列
newScheduledThreadPool()
几种常见的线程池
线程池
ConcurrentHashMap
CopyOnWriteArrayList
ConcurrentLinkedQueue
BlockingQueue
ConcurrentSkipListMap
并发工具类
多线程中的其他锁
版本号
V:需要读写的内存值(操作时的值)
A:进行比较的内存之(操作之前的值)
B:最新的值
简单的说对一个值进行操作时,这个值操作前后不能改变。
三要素
CAS(比较并交换)是CPU指令级的操作,只有一步原子操作,所以非常快。
介绍
AtomicStampedReference
DCAS
ABA问题
循环开销大
CAS
乐观锁和悲观锁(是一个思想,并不是技术)
自旋锁
synchronized 原理
无锁
通过对比 Mark Word 解决加锁问题,避免执行CAS操作。
偏向锁
通过用 CAS 操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。
轻量级锁
拥有锁的线程以外的线程都阻塞。
重量级锁
四个阶段(synchronized )
锁升级过程
锁的升级
ThreadLocal
其他用到的类
原子类
对指定对象加锁,进入同步代码前要获得指定对象的锁。
指定加锁对象
对当前实例加锁,进入同步代码前,要获得当前实例的锁
直接作用于实例方法
对当前类加锁,进入同步代码前要获得当前类的锁
直接作用于静态方法
synchrized
多线程
READ-UNCOMMITTED
避免了脏读
READ-COMMITTED
mysql默认隔离级别
REPEATABLE-READ
所有操作都加锁
SERIALIZABLE
事务隔离级别
脏读
不可重复读
幻读与不可重复读类似,不可重复读针对修改,幻读针对新增。
幻读
丢失修改
可能出现的情况
事务
表锁
行锁
粒度
读锁(共享锁)
写锁(排它锁)
读锁和写锁
MVCC(多版本并发控制)
LBCC
MVCC和LBCC
快照读
当前读
快照读和当前读
锁
主键索引
唯一索引
普通索引
组合索引
B+树(使用这个)
hash表
B树
任意节点的左子树上所有节点值不大于根节点的值,任意节点的右子树上所有节点值不小于根节点的值
有可能成链状,不平衡
二叉树
旋转耗时,实现平衡的关键在于旋转操作:插入和删除可能破坏二叉树的平衡,此时需要通过一次或多次树旋转来重新平衡这个树。
平衡二叉树
确保从根到叶子的最长的可能路径不多于最短的可能路径的两倍长
如何实现平衡
与二叉平衡树对比
对于数据存储在内存中,红黑树表现是优异的,但是对于数据存储在硬盘上的数据来说,红黑树并不擅长,因为红黑树长得还是太高了
红黑树
innoDB索引结构
单表优化
读写分离
缓存
表分区
垂直拆分
水平拆分
nosql数据库
大表优化方案
主服务器
MASTER_LOG_FILE='mysql-bin.000006'(日志文件)
MASTER_LOG_POS=489(类似偏移量之类的)
从主服务器中获取的两个参数(启动时两个必须一样,否则数据同步有问题或者无法同步)
replicate-wild-do-table = test1.table2
设置指定表同步
从服务器
数据延迟
部分数据丢失
有可能的问题
主从同步延迟解决方案
主从同步
MySql
实例化
设置属性值
调用beanNameAware中setBeanName方法,嗲用beanFactoryAware中setBeanFactory方法
beanPostProcessor前置处理方法
InitializingBean中afterPropertiesSet方法
调用init-method中配置的初始化方法
生存期(使用)
DisposableBean的destory方法以及是否配置自定义的销毁方法
销毁
这个方法只是简单的返回我们当前的beanName(获得在配置文件中配置好的name)
BeanNameAware
与beanNameAware类似
BeanFactoryAware
对bean实例初始化的,前置处理以及后置处理
BeanPostProcessor
bean工厂的bean属性处理容器,说通俗一些就是可以管理我们的bean工厂内所有的beandefinition(未实例化)数据,可以随心所欲的修改属性。
BeanFactoryPostProcessor
bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。
InitializingBean
一些相关接口
Bean的生命周期
在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
Aspect
Joint point
表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
可以针对某个包下面,方法以及注解
pointcut
Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
@Around : 环绕通知
Advice
Target
Weaving
AOP(面向切面编程)
一种设计思想:spring中的bean交给spring容器去管理,当用到时从容器中拿取
IOC
构造方法
set
默认根据类型自动装配,如果想按找名称进行注入加上@Qualified注解
@Autowired
默认按名称进行装配
@Resource
注解
注入方式
DI
通过java.lang.reflect.Proxy类来动态生成代理类;
代理类要实现InvocationHandler接口;
由于java的单继承,动态生成的代理类已经继承了Proxy类的,就不能再继承其他的类,所以只能靠实现被代理类的接口的形式,故JDK的动态代理必须有接口。
JDK代理只能基于接口进行动态代理;
首先有需要代理的对象(就是接口)
创建代理类,实现InvocationHandler接口,在invoke方法中写增强的逻辑
ClassLoader:定义了由哪个ClassLoader对象来对生成的代理对象进行加载
Class<?>[] interfaces:new Class[]{Subject.class}
InvocationHandler(我们自己写的代理类)
用Proxy中的newProxyInstance 方法得到一个代理对象(三个参数)
使用过程
JDK
创建被代理类
代理类
执行
CGLIB
JDK和CGLIB区别
动态代理
Spring
在调用接口时,使用了jdk动态代理生成了代理类,代理类中执行了相应的sql逻辑
为什么mapper中是接口也还可以使用
mybatis
发送请求到前端控制器DispatcherServlet
前端控制器调用处理器映射器
处理器映射器根据注解找到对应的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
DispatcherServlet调用HandlerAdapter处理器适配器。
HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
Controller执行完成返回ModelAndView。
HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
ViewReslover解析后返回具体View。
DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
DispatcherServlet响应用户。
工作原理
SpringMVC
底层是@Configuration注解,就是支持javaConfig代替xml配置
@SpringBootConfiguration
自动配置注解,这个注解可以帮助我们自动载入应用程序所需要的所有默认配置。
内部实际上就去加载META-INF/spring.factories文件的信息,然后筛选出以EnableAutoConfiguration为key的数据,加载到IOC容器中,实现自动配置功能!
@EnableAutoConfiguration
扫描注解,默认是扫描当前类下的package。@Controller/@Service/@Component/@Repository等注解加载到IOC容器中
@ComponentScan
@SpringBootApplication
自动配置如何实现的
springboot
观察者模式
装饰着模式
工厂模式
单例模式
适配器模式
代理模式
模板方法模式
外观模式
状态模式
设计模式
JAVA
0 条评论
回复 删除
下一页