@lxx3061313
2018-12-04T11:41:45.000000Z
字数 17434
阅读 370
要点
https://juejin.im/post/5ab1a338518825558a067c1f(带部分答案)
1.面向对象的特征
封装,继承,多态
封装
:客观事物封装成抽象的类。一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。
继承
:某一个类型的对象获取另一个类型对象的属性和方法的能力,是一般到特殊的过程。方式有:接口继承,和实现类继承。接口可以多继承,实现类不能多继承。
多态
:子类对象赋值给父类引用。使得在不同的内部结构实现下,共享相同的外部接口。
多态实现原理
: 方法表(https://blog.csdn.net/huangrunqing/article/details/51996424)
静态调用
:invokestatic(用以调用类方法),invokespecial(实例初始化方法、私有方法和父类方法)
动态调用
:invokevirtual(类多态的调用指令),invokeinterface(接口多态的调用指令)
2.final, finally, finalize 的区别
final
:修饰符,在类上修饰,该类不能被继承,在方法上修饰,该方法不能被重写。在变量上修饰,改变量在初始化的时候必须赋值,后面只能读取。
finally
:用于在try,catch,finally程序模式中。
finalize
:方法名,在Object类中定义,子类可以重写。这个方法是由垃圾收集器来调用的,java允许使用finalize方法在垃圾收集器将要把对象清理出去的时候,对象使用这个方法做必要的清理工作(这里有一个误区)。需要注意的是,finalize方法在内存回收的时候只会被调用一次,即第一次扫描到该对象以为不可达,那么会判断finalize是否已经调用过,如果没有则放入队列,由低优先级的线程去执行,不保证执行完毕,所以其实这个方法不能用来做清理动作。如果已经调用过,则不会再调用了,直接清理。
3.int 和 Integer 有什么区别
基本区别
:int是基本类型,Integer是int的包装类型,Integer需要实例化对对象才能使用。Integer默认为null,int默认为0.
比较方面的区别
:new Integer和new Integer直接比较不会拆箱,所以为false. int和new Integer比较会触发拆箱返回true. Integer直接赋值和new Integer也会是false,一个在常量池,一个在堆中。对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true
4.重载和重写的区别
重写
:子类对父类允许访问的访问重写编写,方法的返回值和参数列表不能变,抛出的异常也不能多。
重载
:统一类中,方法名相同,参数列表不同的重新编写。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载是一类中多态性的一种表现。
5.抽象类和接口有什么区别
抽象类
:被用来创建继承层级里子类的模板。捕捉子类的通用特性。不能被实例化。
接口
:抽象方法集合。可以被多继承,实现接口必须去报。
什么时候使用
:如果有一些方法有默认的实现,或者基本功能总是在变化,那么使用抽象类。如果希望多继承,并且接口基本不变用接口。另外在面向接口编程中,在面向服务的编程中,都使用接口。
6.说说反射的用途及实现
功能
:运行时获取一个对象所属的类,索取一个类的所有方法和属性,运行时创建对象。运行时调用对象的方法。
用途
: spring的bean管理和初始化都是用的反射。
7.说说自定义注解的场景及实现
order actor,spring retry,emqConsumer
8.HTTP 请求的 GET 与 POST 方式的区别,HTTP https
get,post就不说啦。
9.session 与 cookie 区别
10.session 分布式处理
11.JDBC 流程
12.MVC 设计思想
13.equals 与 == 的区别
14 引用
https://blog.csdn.net/mazhimazh/article/details/19752475
https://blog.csdn.net/jiangjiajian2008/article/details/52929843i
15 内存屏障
http://blog.jobbole.com/53697/
16 jdk9:增加了平台模块化系统,集合增加了一些方便的方法来创建不可变集合。jdk10: var 局部变量类型推断。G1 垃圾回收器的并行完整垃圾回收
301 vs 302
https://www.jianshu.com/p/995a3000f7d6
301永久性跳转,302临时性跳转,有URL劫持的可能。
https://www.jianshu.com/p/9db57e761255
对称加密 & 非对称加密
:对称加密,加密和解密用相同的密钥。非对称加密,分为私钥和公钥,私钥加密可以公钥解密,公钥加密可以私钥解密。
数字签名
:数字签名是公钥密码的逆应用,即私钥加密,公钥解密。用私钥加密的信息是签名,只有私钥拥有者才可以。用公钥解密这一步骤成为验证签名,所有拥有公钥的都可以。
生成签名
:消息发送者A,对消息计算hash值,用私钥A加密hash值(签名),将签名附属在消息后面一同发送给消息接收者B。
验证签名
:B接收到消息后,提取签名,用公钥A解密签名,获得hash值,然后将消息进行hash计算,对比hash值,确认消息是否发生了串改。
证书
:对公钥进行数字签名,有CA颁发,用来证明某个服务器的公钥是合法的,没有被串改过的。
如何生成证书
:服务器把公钥A发给CA,CA用自己的私钥B给公钥A加密,并生成数字签名,CA把数字签名,公钥以及一些服务器信息发送给服务器。
如何验证证书
:客户端拿到证书,客户端使用CA给的公钥B解密证书里面的数字签名,得到服务器的公钥A的hash值,客户端对公钥进行hash计算,对比解密出的hash值,如果一样则验证通过。
https如何加密传输
:混合加密方式,1.通过非对称加密传送用于后期消息传递的对称加密密钥。2. 使用对称密码算法进行消息的传递。
为什么是混合加密
:因为非对称算法成本比较高,用来传递消息会增加系统负载。
https整个交互流程
:1.服务器A将自己的公钥A登录值CA进行验证。2.CA使用自己的私钥B对服务器A的公钥A生成证书。3.客户端拿到服务器A的公钥证书。使用CA的公钥B对证书解密,拿到服务器的公钥A,并对比hash值验证服务器公钥A的合法性。4.验证通过后使用服务器A的公钥A加密对称加密密钥C,并发送给服务器A.5服务器A拿到消息后,使用私钥A解密消息,拿到对称加密的密钥C. 6.使用对称加密密钥A进行消息通信。
https整个交互流程2
:1.用户向web服务器发起一个安全连接的请求2.服务器返回经过CA认证的数字证书,证书里面包含了服务器的public key(公钥)3.用户拿到数字证书,用自己浏览器内置的CA证书解密得到服务器的public key4.用户用服务器的public key加密一个用于接下来的对称加密算法的密钥,传给web服务器(因为只有服务器有private key可以解密,所以不用担心中间人拦截这个加密的密钥)
5.服务器拿到这个加密的密钥,解密获取密钥,再使用对称加密算法,和用户完成接下来的网络通信i
https://www.jianshu.com/p/3c7a0771b67e
维持TIME_WAIT有两个原因:
1.可靠地实现TCP的全双工连接终止。
2.允许旧的重复数据段在网络中过期
http://calvin1978.blogcn.com/articles/collection.html java集合小抄,非常精华的总结
1.List 和 Set 区别
2.List 和 Map 区别
3.Arraylist 与 LinkedList 区别
4.ArrayList 与 Vector 区别
5.HashMap 和 Hashtable 的区别
6.HashSet 和 HashMap 区别
7.HashMap 和 ConcurrentHashMap 的区别
https://yikun.github.io/2015/04/01/Java-HashMap%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%AE%9E%E7%8E%B0/ 分析的很明白。i
http://www.importnew.com/7099.html 从面试者的角度考虑
成员变量
:Node[] table, size, threshold, loadFactor. table是哈希表,表中每个元素都是一个单链表。size表示当前map拥有的kv值个数。Node是一个内部类,每个Node代表一个实际的kv。threshold表示阈值,size大于threshold时需要对map进行或者,而且threshhold=table.length * loadFactor(默认0.75).
put操作
:对key计算hash, 如果是第一次put需要初始化table,否则计算index,如果没有碰撞则直接放入table[i]里。如果碰撞了以链表存在table[i], 如果碰撞了并且列表长度超过了阈值(8),则转为红黑树。如果节点存在就替换。table.size超过了阈值则resize().
get操作
:计算key的hash,计算index,如果是第一个元素则命中,否则需要在table[i]对应的列表或者tree里搜索。
hash的计算方式
:(h = key.hashCode()) ^ (h >>> 16); 即高16位异或低16位。因为想高16位也要参与一下计算。减少碰撞。
计算index的方式
:index=(n-1)&hash,等效于%操作。
resize
:扩展为原来table.size的两倍。元素的位置要么是在原位置,要么是在原位置再移动2次幂的位置。我们在扩充HashMap的时候,不需要重新计算hash,只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”。这个设计确实非常的巧妙,既省去了重新计算hash值的时间,而且同时,由于新增的1bit是0还是1可以认为是随机的,因此resize的过程,均匀的把之前的冲突的节点分散到新的bucket了。
HashMap遍历
:抽象类HashIterator,其他三种遍历方式KeyIterator,ValueIterator,EntryIterator都继承与它。
1.创建线程的方式及实现
new Thread,继承Runable,Callable
2.sleep() 、join()、yield(),wait()有什么区别
sleep
:当前线程暂停执行指定的时间。不释放锁。
wait
:使线程进入waiting/time_waiting状态。等待其他线程通过notify唤醒。线程协作机制的底层实现。会释放当前锁。waite()和notify()必须在synchronized函数或synchronized block中进行调用
yield
:暂停当前正在执行的线程对象,使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行,通常只是建议,不会强制。
join
:等待线程中终止,通常用于主从线程协作场景。
3.说说 CountDownLatch 原理
https://www.cnblogs.com/200911/p/6059719.html
CountDownLatch是一个线程同步工具,允许一个线程或者多个线程等待其他线程完成操作。
原理
:CountDownLatch通过AQS里面的共享锁来实现的,在创建CountDownLatch时候,会传递一个参数count,该参数是锁计数器的初始状态,表示该共享锁能够被count个线程同时获取。当某个线程调用CountDownLatch对象的await方法时候,该线程会等待共享锁可获取时,才能获取共享锁继续运行,而共享锁可获取的的条件是state == 0,而锁倒数计数器的初始值为count,每当一个线程调用该CountDownLatch对象的countDown()方法时候,计数器才-1,所以必须有count个线程调用该countDown()方法后,锁计数器才为0,这个时候等待的线程才能继续运行。
4.说说 CyclicBarrier 原理i
它要做的事情是让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时候,屏障才会开门。所有被屏障拦截的线程才会运行。CyclicBarrier是由ReentrantLock可重入锁和Condition共同实现的
5.说说 Exchanger 原理
https://blog.csdn.net/carson0408/article/details/79477280
6.说说 CountDownLatch 与 CyclicBarrier 区别
6.1CountDownLatch是一个线程同步工具,允许一个线程或者多个线程等待其他线程完成操作,有主从机制。CyclicBarrier是线程之间互相等待,线程间是平等的等待关系,任何一个线程完成之前,所有线程都必须等待。
6.2CountDownLatch的计数器是一次性的,CyclicBarrier计数器可以循环使用。
7.ThreadLocal 原理分析
每个 线程 都有 一个 Map, 类型 为 ThreadLocalMap, 调用 set 实际上 是在 线程 自己的 Map 里 设置 了 一个 条目, 键 为 当前 的 ThreadLocal 对象, 值 为 value。 ThreadLocalMap 是一 个 内 部类, 它是 专门 用于 ThreadLocal 的, 与 一般 的 Map 不同, 它的 键 类型 为 WeakReference< ThreadLocal>。看看引用
8.讲讲线程池的实现原理
线程 池 主要 由 两个 概念 组成:一个是任务队列; 另一个 是 工作者 线程。 工作者 线程 主体 就是 一个 循环, 循环 从 队列 中 接受 任务 并 执行, 任务 队列 保存 待 执行的任务。
优点:重用线程,避免创建线程开销。任务过多,通过排队解决。
参数:1.线程池大小,corePoolSize,maximunPoolSize,keepAliveTime。2.Queue.3.任务拒绝策略4。线程工厂。
9.线程池的几种方式
SingleThreadExecutor,FixThradPool,CacheThreadPool
10.线程的生命周期
状态:NEW, TERMINATED,BLOCKED,WAITING,TIME_WAITING
11.谈谈对多线程的理解
http://www.importnew.com/18459.html
用途
:1.利用多核CPU。2.防止阻塞。3.方便建模。
线程生命周期
:创建:继承Thread, 实现Runnable.结束:终端。线程各种状态。
线程间的关系
:竞争,协作。
引发的问题
:竞态条件,内存可见性(包含了指令重排序)
解决方案
:竞态条件的解决方案:synchronized, lock, atomic变量。内存可见性:volatile,各种锁。协作方案:synchronized->(wait,notify), lock.condition->(await,signal)
实现方式
:对象monitor,CAS,AQS
并发容器
:concurrentHashMap,CopyOnWriteList,ConcurrentSkipListMap,并发队列。
异步任务执行
:Future,FutureTask,ExecuteService,Runnable,Callable,ThreadExecutorPool
同步协作工具
:CountLatchDown,CyclicBarrier,Samephore,ReentrantReadWriteLock
https://www.jdon.com/performance/threadpool-forkjoin.html
https://blog.csdn.net/chunlongyu/article/details/52518502
volatile:细看一下
1.内存可见性
当写一个volatile变量时,JMM会把该线程对应的本地内存中的变量强制刷新到主内存中去;这个写会操作会导致其他线程中的缓存无效。
2.禁止指令重排序
synchronize 实现原理
synchronized 与 lock 的区别
ABA 问题
乐观锁的业务场景及实现方式
3. 分布式锁怎么实现
http://www.hollischuang.com/archives/1716
数据库实现,缓存实现,zk实现
数据库版本
:1. 创建单独锁表,插入成功代表获得锁,删除记录代表释放锁,存在问题:数据库单点,不阻塞,不可重入,没有超时时间。2.利用Innodb的排它锁,在相关记录上用for update。存在问题:单点,不可重入,行锁可能在数据量少的时候升级为表锁。
缓存版本
:原子操作锁的key。缺点:超时时间不太好掌握。好处:性能好,集群部署,有很多现成的分布式锁算法。
zk版本
: 可以实现两种锁,1.独占锁,就是所有试图获得锁的线程,最终只会有一个获得。只要创建一个临时节点就行,创建成功的获得锁。2. 控制时序锁,就是所有试图获得锁的客户端都会执行,只是有个全局时序罢了。创建临时有序节点,创建成功并且序列里面值最小的获取锁成功,其他节点等待时序节点比自己小的节点释放自己的锁,使得自己持有的序列成为最小。
为什么要有内存模型一说
:java虚拟机规范想通过定义出一种内存模型来屏蔽掉各种硬件和操作系统的内存访问差异,以达到一次编译到处运行的效果。 内存模型做了什么事情
:内存模型定义了程序访问变量的规则,即应该怎么把变量存储在内存和怎么从内存中取数据。 内存模型怎么做的
:定义了工作内存和共享内存。2.GC
https://blog.csdn.net/FIRE_TRAY/article/details/51320597
https://liuzhengyang.github.io/2017/04/01/understandinggarbagecollect/
https://blog.csdn.net/YHYR_YCY/article/details/52566105
对象死亡判断方法
:引用计数,可达性分析。
垃圾收集算法
:标记清除,复制,标记整理,分代收集。
垃圾收集器
:Serial,ParNew,Parallel Scavenge, Serial Old,Parallel Old, cms, g1
Serial
: 单线程,暂停所有的用户线程,新生代收集器,使用复制算法,可以和CMS配合。
ParNew
: Serial的多线程版本,也会暂停所有的用户线程,使用复制算法,可以和CMS配合。
Parallel Scavenge
: 多线程新生代收集器,不能和CMS配合。关注点在可控制的吞吐量。有自适应调节策略。
Serial Old
:Serial新生代收集器的老年代版本。单线程收集器,使用标记整理算法,会暂停所有的用户线程。在Server版本中,会座位CMS的后备方案,当CMS发生Concurrent Mode Fail时,会启用 。
Parallel Old
:Parallel Scavenge收集器的老年代版本,多线程,标记整理算法。也会暂停用户线程。
CMS
:标记清除算法。4个阶段:初始标记,并发标记,重新标记,并发清除。 初始标记和重新标记需要暂停所有的用户线程。缺点:跟用户线程并发运行,会占用CPU。无法处理浮动垃圾。内存碎片。
G1
: Garbage First, 即优先回收价值大的Region。整体标记整理,局部复制算法,避免了内存随便。通过Region回收优先级建立了可预测的停顿时间模型。通过RememberSet避免了全Region扫描,RememberSet记录了引用之间的关系。回收步骤:初始标记,并发标记,重新标记,筛选回收。
G1-重新标记
:而最终标记阶段则是为了修正在 并发 标记期间因用户程序 继续 运作 而 导致 标记 产生 变动 的 那一 部分 标记 记录, 虚拟 机 将 这段 时间 对象 变化 记录 在 线程 Remembered Set Logs 里面, 最终 标记 阶段 需要 把 Remembered Set Logs 的 数据 合并 到 Remembered Set 中, 这 阶段 需要 停顿 线程, 但是 可 并行 执行。
G1-筛选回收
:最后 在 筛选 回收 阶段 首先 对 各个 Region 的 回收 价值 和 成本 进行 排序, 根据 用户 所 期望 的 GC 停顿 时间 来 制定 回收 计划,
为什么新生代要分eden,survivorA,survivorB
:新生代基于复制算法实现,因为新生的对象存活率很低,所以通过复制算法,可以移动很少的一部分对象来达到gc目的,而且解决了内存碎片问题。
cms gc流程
:初始标记,并发标记,重新标记,并发清除。缺点:浮动垃圾,内存碎片。i
准确式GC
:让JVM知道内存中某些位置是什么数据类型,比如当前内存位置是一个整数数据,还是一个引用。这样JVM可以很快的确定所有引用类型的位置,从而可以更有针对性的进行GCROOTS枚举。
OopMap
: hotspot使用oopmap来实现准确式gc,HotSpot 就将对象内存布局之中什么偏移量上数值是一个什么样的类型的数据这些信息存放到 OopMap 中;在 HotSpot 的 JIT 编译过程中,同样会插入相关指令来标明哪些位置存放的是对象引用等,这样在 GC 发生时, HotSpot就可以直接扫描OopMap来获取对象引用的存储位置,从而进行 GC Roots 枚举。
安全点
:
安全区域
:
Minor GC、Major GC和Full GC之间的区别
http://www.importnew.com/15820.html
3.调优
https://juejin.im/post/59f02f406fb9a0451869f01c
4.故障排查
http://www.importnew.com/28916.html
1.MySQL 索引使用的注意事项
2.说说反模式设计
3.说说分库与分表设计
https://www.cnblogs.com/sheseido/p/8880091.html
垂直拆分(专库专用),业务数据清晰,可以实现动静分离,冷热分离等模式。
水平拆分(单表拆多表),拆分方式:hash路由,时间路由
4.分库与分表带来的分布式困境与应对之策
存在分布式事务问题,跨节点join问题,跨节点合并,排序分页问题,多数据源管理问题。
分布式事务:xa协议,两阶段协议。
5. 索引,事务,锁,B+树,聚集索引,非聚集索引
6. 倒排索引,es
有哪些类型
string,list,hash,set,zset
string底层数据结构由int,embstr,raw三种数据结构支持。
list底层数据结构有ziplist,linkedlist两种数据结构支持。
hash底层数据结构有ziplist,ht支持
set底层数据结构有intset,ht支持
zset底层数据结构有ziplist,skiplist支持
2.Redis 内部结构
2.1 字典(ht)
redis内部的kv数据库,通过取模来计算槽位,通过链表和红黑树解决冲突。每个字典自带两个hash表,一个平时使用,一个用来rehash
2.2 raw,embstr
embstr,当字符串长度小于32字节,则底层用embstr保存,embstr是专门用于保存短字符串的,相比raw,embstr只会调用一次内存分配。
raw, 字符串长度大于32字节,会采用raw,会调用两次内存分配,相应的,也会调用两次释放。
2.3 skiplist
zset的底层实现之一。
2.4 intset
2.5 ziplist
压缩列表是Redis为了节省内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型数据结构.一个压缩列表可以包含多个节点,每个节点可包含一个字节数组或一个整数值.列表键包含少量列表项,每个列表项均不是长字符串(小整数或短字符串)
3.Redis 持久化机制
rdb
aof
4.Redis 集群方案与实现
4.1 复制,复制包含两部分:同步和命令传播,同步通过生成RDB文件让从服务器来完成同步,命令传播用于同步完成后,每次主服务器写操作,将写命令同步给从服务器。部分重同步,2.8版本以前每次都是完成生成rdb,2.8版本后增加了部分重同步模式,实现方式:1)主从保持一个复制偏移量,2)主维护一个复制积压缓冲区(固定大小先进先出队列),3)从保存主服务器id。
5.Redis 为什么是单线程的
https://blog.csdn.net/chenyao1994/article/details/79491337
因为CPU不是redis的瓶颈,最有可能成为redis瓶颈的是内存和网络带宽。官方测试redis在单进程单线程模式下,连接数少于10000的情况下,qps可以达10万+。那么问题来了redis为什么这么快:1)存内存操作。2)定制化的数据结构。3)io多路复用。4)单进程单线程,避免上下文切花,避免锁开销。
6.缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
缓存雪崩
:大量缓存在同一个时间内过期,导致压力全部到数据库。这里提出了三种方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一各被称为“二级缓存”的解决方法
缓存穿透
:缓存穿透是指用户查询数据库没有的数据,缓存中自然也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。最长见的有空对象和布隆过滤器两种解决方案
缓存预热
:系统启动时就将数据加载到缓存中。当然量少时,这种操作不是必须的。
缓存更新
:惰性更新,用户查询的时候不存在则更新。主动更新,通过task来定时更新。
字典rehash
:
7.redis 大key问题
概念
:单个key的value过大,或者hash,set,zset,list的存储元素过多。
单个key的value过大
:如果需要整存争取则拆分成多个key-value,通过mutiget获取。降低单词操作的压力。如果不需要整存整取,也拆分成多个key-value,使用hash存储,hget,hmget读取。
hash,set,zset,list存储过多元素
:将元素拆分,在应用层通过类似取模的操作将key分拆多个key。每次存取需要在应用层先计算key。然后再去redis取。如果有对时间的要求,可以按时间拆分。类似于分库分表。
大key的问题
:网卡可能会成为瓶颈,qps会严重受到影响。单个key删除会将整个redis server卡主。
``
1.BeanFactory 和 ApplicationContext 有什么区别
BeanFactory是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能;BeanFactory在启动的时候不会去实例化Bean,中有从容器中拿Bean的时候才会去实例化.
ApplicationContext应用上下文,继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能:国际化,访问资源(ResourceLoader),消息发送、响应机制(ApplicationEventPublisher),AOP(拦截器),载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层.
ApplicationContext在启动的时候就把所有的Bean全部实例化了
2.Spring Bean 的生命周期
2.1 bean自身的方法:构造函数,set函数设置属性值,init-method,destroy-method。
2.2 bean级生命周期方法BeanNameAware,BeanFactoryAware,InitializingBean,DisposableBean
2.3 InstaniationAwareBeanPostProcessor,BeanPostProcessor等后处理器。
3.Spring IOC 如何实现
http://www.360doc.com/content/17/0917/07/2708086_687778967.shtml
spring通过一个配置文件描述bean以及bean之间的依赖关系,利用java语言的反射功能实例化bean以及装配bean,spring在完成这些底层的基础功能上还提供了bean实例缓存,生命周期管理,事件发布,资源装载等高级功能。
4.Spring AOP
http://www.importnew.com/24305.html
AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理、日志、缓存等等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理,静态代理的代表为AspectJ;而动态代理则以Spring AOP为代表。本文会分别对AspectJ和Spring AOP的实现进行分析和介绍。
所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和Proxy类。
如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
AspectJ在编译时就增强了目标对象,Spring AOP的动态代理则是在每次运行时动态的增强,生成AOP代理对象,区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
5.Spring 事务
概念
:Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:1. connect,2. start tans 3. curd, 4.commit/rollback
使用Spring的事务管理功能后,我们可以不再写步骤 2 和 4 的代码,而是由Spirng 自动完成.
原理
:1.在相关的类和方法上通过注解@Transactional标识,2.spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入,这样就在代理中为我们把相关的事务处理掉了。3.真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
传播
:REQUIED(默认,外层有事务则运行在外层事务中,没有则自己心起事务)。NEW(每次都新起事务,外层有事务,则挂起)。SUPPORT(外层有事务则在外层事务运行,没有则以非事务运行)。NESTED(外层有事务,则以嵌套事务运行,没有则以REQUIED模式运行)
6.Spring MVC 运行流程
https://blog.csdn.net/cswhale/article/details/16941281
6.1客户端请求提交到DispatcherServlet
6.2由DispatcherServlet控制器查询一个或多个HandlerMapping,
6.3找到处理请求的ControllerDispatcherServlet将请求提交到Controller
6.4Controller调用业务逻辑处理后,返回ModelAndViewDispatcherServlet查询一个或多个ViewResoler视图解析器,
6.5找到ModelAndView指定的视图
6.6视图负责将结果显示到客户端
7.Spring MVC 启动流程
https://www.jianshu.com/p/dc64d02e49ac 写的不错
0. tomcat web容器启动时会去读取web.xml,相关组件的启动顺序为:解析<context-param>->解析listener->解析filter->解析servlet。具体过程如下
1. 解析<context-param>的键值对,创建一个application的内置对象即ServletContext,servlet上下文,用于全局共享。将<context-param>的键值对放入ServletContext上下文中共web全局共享。
2. 读取<listener>标签,创建监听器,一般会使用ContextLoadListener类,如果使用了ContextLoadListener,Spring会创建一个WebApplicationContext对象,WebApplicationContext就是ioc容器,ContextLoadListener创建的WebApplicationContext是根ioc容器,全局共享的。放在ServletContext,键为一个固定值。这个全局的根IoC容器只能获取到在该容器中创建的Bean不能访问到其他容器创建的Bean,也就是读取web.xml配置的contextConfigLocation参数的xml文件来创建对应的Bean。
3. listener创建完成后如果有<filter>则会去创建filter。
4. 初始化创建<servlet>,一般使用DispatchServlet类。
5. DispatchServlet的父类FrameworkServlet会重写起父类的initServletBean方法,并调用initWebApplicationContext方法和onFresh()方法。
6. initWebApplicationContext方法会创建一个当前Server的子ioc容器,如果存在上述的根容器,则设置起根容器,没有则创建一个根容器。
7. 读取<servlet>标签的<init-param>配置的xml文件并加载相关Bean。
8. onRefresh()方法创建Web应用相关组件。
8.Spring 的单例实现原理
https://juejin.im/post/594084fd61ff4b006cb425f1
Spring 对 Bean 实例的创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是 ConcurrentHashMap 对象。
1.什么是TCP 粘包/拆包
粘包
:客户端一共发了两条完整的消息,对应到两个数据包,第一个数据包包含第一个消息的完整数据和第二个数据包的部分数据,第二个数据包包含第二个消息剩下的数据。
拆包
:上述情况下,第二个消息就涉及到了拆包。
原因
:应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包。接收方法不及时读取套接字缓冲区数据,这将发生粘包。
解决方案
:1.使用带消息头的协议 2.设置定长消息 3.设置消息边界
2.Netty 线程模型
http://www.infoq.com/cn/articles/netty-threading-model 写的不错
对于主从Reactor模型,1.从主线程池中随机选择一个Reactor线程作为Acceptor线程,用于绑定监听端口,接收客户端连接;2.Acceptor线程接收客户端连接请求之后创建新的SocketChannel,将其注册到主线程池的其它Reactor线程上,由其负责接入认证、IP黑白名单过滤、握手等操作;3.步骤2完成之后,业务层的链路正式建立,将SocketChannel从主线程池的Reactor线程的多路复用器上摘除,重新注册到Sub线程池的线程上,用于处理I/O的读写操作。
服务端线程模型
监听线程跟io线程分离,跟reactor模型很像。
1. 创建服务端,生成两个EventLoopGroup,一个是负责监听连接,一个负责io。每个group的线程数可以参数指定。
2. 从bossGroup线程池中选择一个EventLoop注册到多路复用器上,用来监听端口。
3. 如果监听到客户端连接,则创建socketChannel,并注册到workerGroup上。
4. 选择完workerGroup的EventLoop后,注册到多路复用选择器上(其实就只这个EventLoop)。监听io操作。
5. 处理io
说说 Netty 的零拷贝
https://segmentfault.com/a/1190000007560884
OS层面的0拷贝,netty层面的0拷贝
Netty 内部执行流程
https://blog.csdn.net/truong/article/details/62231036
https://zhuanlan.zhihu.com/p/36528189
4.dubboi
分布式session
https://www.jianshu.com/p/221f8a42be33
分布式锁怎么实现
http://www.hollischuang.com/archives/1716
你系统中的前后端分离是如何做的
说说你的开发流程
你和团队是如何沟通的
1. 团队思维,强势的干预以达成某种结果,并不是最佳选择,统一协调思维,共用一个大脑思考和决定,才是最优的结果,哪怕反对者只是一个微足不道的人,也要以团?的关怀去理性说服,避免出现裂痕。
2. 团队语言,不管你想表达什么样的观点,都要使用团队其他成员能接受的语言,不能唯我独尊,锋芒毕露,伸出刀子来就想扎人。团队中的人,性格各异,利益牵涉不清,不可能永远没有冲突或矛盾,各怀鬼胎是一定的。但这不意味着你要把责任讲到明面上,放到台前来,不是他死就是你亡,而应以团队化的沟通方式进行解决,照顾每个人的感受。
3. 团队 logo,在同一团队“脸谱”下的平等交流,制定和建设使每一类成员受益的团队文化,是合格管理者的任务。注意某些在某种文化上格格不入的同事。
4. 团队协调,管理者的协调能力,首先表现在对于工作的分配和奖惩,其次才是做调解下属利益的“马大姐”。工作不是让你来发扬爱心和善心的地方,主次颠倒的结果就是你获得了一个好名声,却毁掉了自己的事业。奖惩分明,结果导向。
你如何进行代码评审
以分享的形式展示,在每次项目提测前进行。分为:1.项目背景。2.功能拆分。2.详细设计(代码设计,架构设计)。3.模块代码分享。
全部开发参加,并提供反馈。对相关点可能会进行扩展。
目的:1.提升同学的总结能力。2.表达能力。3.对于好的代码规范要实时的普及。不好的习惯要矫正。
说说你对技术与业务的理解
说说你在项目中经常遇到的 Exception
说说你在项目中遇到感觉最难Bug,怎么解决的
说说你在项目中遇到印象最深困难,怎么解决的
你觉得你们项目还有哪些不足的地方
你是否遇到过 CPU 100% ,如何排查与解决
http://www.importnew.com/28916.html
你是否遇到过 内存 OOM ,如何排查与解决
http://www.importnew.com/28916.html
性能调优
https://juejin.im/post/59f02f406fb9a0451869f01c
说说你对敏捷开发的实践
https://www.zhihu.com/question/19645396
说说你对开发运维的实践
介绍下工作中的一个对自己最有价值的项目,以及在这个过程中的角色
说说你的亮点
说说你最近在看什么书
说说你觉得最有意义的技术书籍
工作之余做什么事情
说说个人发展方向方面的思考
说说你认为的服务端开发工程师应该具备哪些能力
说说你认为的架构师是什么样的,架构师主要做什么
https://www.zhihu.com/question/19558112
https://blog.csdn.net/hguisu/article/details/38385371
说说你所理解的技术专家
你为什么离开之前的公司
你为什么要进我们公司
说说职业规划
你如何看待加班问题
谈一谈你的一次失败经历
你觉得你最大的优点是什么
你觉得你最大的缺点是什么
你在工作之余做什么事情
你为什么认为你适合这个职位
你觉得自己那方面能力最急需提高
你来我们公司最希望得到什么
你希望从这份工作中获得什么
你对现在应聘的职位有什么了解
您还有什么想问的
你怎么看待自己的职涯
谈谈你的家庭情况
你有什么业余爱好
你计划在公司工作多久
作者:梁桂钊
链接:https://juejin.im/post/5ab1a338518825558a067c1f
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
八皇后:https://www.cnblogs.com/bigmoyan/p/4521683.html
https://www.jianshu.com/p/f99df1f47232
https://hufangyun.com/2017/short-url/
微信红包架构
http://www.infoq.com/cn/articles/2017hongbao-weixin
CDN科普
https://www.zhihu.com/question/37353035
阿里面试的三个层次
https://www.imooc.com/article/24852?block_id=tuijian_wz