Java高级知识储备-持续更新...
2021-05-10 16:05:04 108 举报
AI智能生成
Java高级工程师知识储备,持续更新...
作者其他创作
大纲/内容
设计模式
单例模式
饿汉式
懒汉式(线程安全)
静态内部类
枚举
双重校验锁
工厂模式
简单工厂模式
工厂方法模式
抽象工厂模式
简单工厂和抽象工厂有什么区别
继承模板方法设计模式
代理模式
静态代理
动态代理
JDK动态代理
CGLib动态代理
观察者模式
装饰者模式
多线程
1、线程基础、线程
之间的共享和协作
基础概念
CPU核心数,线程数
CPU时间片轮转机制
进程
进程调度算法
线程
线程调度算法
协成
优缺点
高并发编程的意义、好处和注意事项
并发和并行的区别
并行parallellism
并发concurrency
2、Java中线程基础
启动和终止线程
创建并启动线程四种方式
理解中断
如何安全的终止线程
线程再认识
线程常用方法
线程的状态
线程的优先级
Demon线程
线程间的共享
synchronized
对象锁
类锁
volatile
ThreadLocal
`ThreadLocal`为什么容易内存泄漏
为什么使用ThreadLocal为弱引用而不是强引用
了解`volatile`关键字不?能否解释下,然后这和`synchronized`有什么大的区别
线程间协作
等待和通知机制
Wait,Notify/NotifyAll
等待和通知的标准范式
notify和notifyAll应该用谁
Join方法
调用yield() 、sleep()、wait()、notify()等方法对锁有何影响?
是否了解多线程开发里面常用的方法,`sleep`/`yield`/`join`/`wait`/`notify`/`notifyAll`, 分别解释下
线程状态
画下线程的状态转换图和这些转换过程常用的`api`也标记下
使用多线程场景
在`Java`中可以有哪些方法来保证线程安全
平时多线程用的挺多的,写出`3`条你遵循的多线程最佳实践
并发编程工具类
同步容器
Hashtable
Vector
Stack
同步工具类包装Collections.synXXX
并发容器
ConcurrentHashMap
put流程
CopyOnWriteArrayList
ConcurrentSkipListMap
ConcurrentSkipListSet
线程安全的Queue队列
使用场景
阻塞型
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
DelayQueue
SynchronousQueue
LinkedTransferQueue
LinkedBlockingDeque
ArrayBlockingQueue和LinkedBlockingQueue区别
非阻塞型
ConcurrentLinkedQueue
它怎么实现线程安全的
阻塞队列和非阻塞队列区别
并发安全
类的线程安全
如何做到类的线程安全
无状态
让类不可变
更多......
线程不安全引发的问题
死锁
原因
表现
检测和解决
活锁
多线程程序
性能和思考
影响性能的因素
减少锁的竞争
线程安全的单例模式
如何让双重检查锁定安全
懒汉式
饿汉式
线程的并发工具类
Fork/Join
什么是分而治之?
工作密取
使用的标准范式
CountDownLatch作用、应用场景和实战
countdownlatch和join方法的区别
CyclicBarrier作用、应用场景和实战
CountDownLatch和CyclicBarrier辨析
Semaphore作用、应用场景和实战
Exchange作用、应用场景和实战
Callable、Future和FutureTask
原子操作CAS
原子操作类
CAS的原理
CAS的问题
ABA问题
开销
只能保证一个共享变量的原子操作
原子操作类的使用
基本类型
数组
引用
带版本戳
显式锁和AQS(AbstractQueuedSynchronizer)
显式锁
Lock接口、核心方法和使用
Lock接口和synchronized的比较
ReentrantLock
可重入锁
锁的公平和非公平
ReentrantReadWriteLock
ReadWriteLock接口
使用场景
Condition接口
用处
用Lock和Condition实现等待通知
了解LockSupport
AbstractQueuedSynchronizer
什么是AQS?学习它的必要
AQS使用方式和其中的设计模式
AQS同步方式
了解其中的方法
实现一个自己的独占锁
深入源码
AQS中的数据结构
节点在同步队列中的增加和移出
独占式同步状态获取与释放
共享式同步状态获取与释放
Condition分析
等待队列
await方法
signal方法
了解ReentrantLock的实现
源码
锁的可重入
公平和非公平锁
你可以说清`ReentrantLock`和`synchronized`的差别不
了解ReentrantReadWriteLock的实现
设计一个缓存组件 或 提高`Collection`的并发性
知道`ReentrantReadWriteLock`吗?和`ReentrantLock`有啥不同
并发容器
ConcurrentHashMap
使用
实现
基本思想
预备知识
Hash
位运算
jdk1.7
构造方法
如何定位
get方法
put方法
扩容
jdk1.8
构造方法
如何定位
get方法
put方法
扩容
其他并发容器
ConcurrentSkipListMap等
了解什么是SkipList
ConcurrentLinkedQueue
写时复制容器
阻塞队列
概念
生产者消费者模式
并发编程里面解决生产消费者模型你知道哪几种方式
常用方法
常用阻塞队列辨析
·ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
·LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
·PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
·DelayQueue:一个使用优先级队列实现的无界阻塞队列。
·SynchronousQueue:一个不存储元素的阻塞队列。
·LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
·LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
延时队列实战
阻塞队列实现原理
线程池
什么是线程池?为什么要用线程池?
实现一个我们自己的线程池
JDK中的线程池
线程池的创建
提交任务
关闭线程池
线程池工作机制
合理配置线程池
系统为我们预定义的线程池
FixedThreadPool
SingleThreadExecutor
CachedThreadPool
WorkStealingPool
含义
使用场景
ScheduledThreadPoolExecutor
含义
使用场景
内部方法辨析
newFixedThreadPool
newCachedThreadPool
newSingleThreadExecutor
newScheduledThreadPool
Executor框架
线程池不允许使用 `Executors` 去创建,要通过 `ThreadPoolExecutor`的方式原因
`ThreadPoolExecutor`构造函数里面的参数你是否掌握,能否解释下各个参数的作用
CompletionService
使用
优点
线程池的5中状态和切换
JMM和底层实现原理
现代计算机物理
上的内存模型
概念
带来的问题
Java内存模型
(JMM)
JVM对Java内存
模型的实现
带来的问题
重排序
类型
依赖性
as-if-serial
重排序带来的问题
内存屏障
临界区
Happens-Before
定义
规则
volatile的内存语义
概念和深入理解
内存语义的实现
重排序规则
内存屏障插入策略
锁的内存语义
final的内存语义
volatile的实现原理
synchronized的实现原理
`jdk1.6`后进行了优化,你知道哪些大的变化
概念
编发编程三要素
各种锁
悲观锁
乐观锁
公平锁
非公平锁
可重入锁
设计一个简单的可重入锁
不可重入锁
设计一个简单的不可重入锁
自旋锁
共享锁
互斥锁
死锁
写个多线程死锁的例子
那上面的例子怎么解决死锁,优化下代码
`Synchronized`锁的升级
分段锁
行锁
表锁
锁的取舍
算法
排序算法
HASH算法
加密算法
对称加密
AES
如何保证KEY的安全性
MD5
非对称算法
RSA
JAVA SE基础
数据类型和运算
数据类型分类以及在`JVM`所占的字节大小
运算符
位运算符和短路运算符
&按位与操作
|按位或操作
&和&&区别
|和||的区别
用最有效率的方法计算`2`乘以`8`
`2`<<`3`
异或运算
实现两个变量交换
加减实现
异或运算实现
算术运算符
i++和++i
关系运算符
==
==和equal方法的区别
面向对象的四大特性
抽象
封装
继承
多态
类和对象
类
值传递和引用传递
形式参数
实际参数
递归
找出某目录下的所有子目录以及子文件并打印到控制台上
`Overload`和`Override`的区别
接口
接口是否可以继承接口?接口是否支持多继承?类是否支持多继承?接口里面是否可以有方法实现?
抽象类
关键字
类的关键作用域
default关键字
serializable接口
serialVersionUID用于控制序列化版本是否兼容
JDK为什么设计为一定要实现serializable接口才能序列化
内部类
对象
实例对象类型
无状态对象
有状态对象
对象的`hashCode()`和`equals()`使用场景
引用
强引用,软引用,弱引用和虚引用
异常
异常处理
try-catch-finally
`try-catch-finally`中`return`执行顺序
`try-with-resource`的使用
从一个`txt`文本里面,拷贝里面的内容到另外一个`txt`文本里面
反射
类库
字符串
String
`String str = new String("1");`创建了几个对象
比较字符串是否相等
字符串拼接比较
HashCode
String、StringBuffer、StringBuilder区别和使用场景
集合
Collection
List
ArrayList
如果需要保证线程安全,`ArrayList`应该怎么做,用有几种方式
LinkedList
Vector
`Vector`和`ArrayList`、`LinkedList`联系和区别?分别的使用场景?
Set
HashSet
LinkedHashSet
TreeSet
`HashSet`和`TreeSet`区别
Map
HashMap
HashTable
LinkedHashMap
TreeMap
WeakHashMap
IdentityHashMap
`HashMap`和`Hashtable`的区别
`HashMap`和`TreeMap`应该怎么选择,使用场景
常见`Map`的排序规则是怎样的
如果需要线程安全,且效率高的`Map`,应该怎么做
为什么`Collections.synchronizedMap`后是线程安全的
`Set`和`Map`的关系
HTTP
http常用状态码
组成
GET 和 POST 有什么区别
缺点
TCP
特点
三次握手
为什么TCP客户端最后还要发送一次确认呢
四次挥手
为什么客户端最后还要等待2MSL
为什么建立连接是三次握手,关闭连接确是四次挥手呢
如果TCP已经建立了连接,但是客户端突然出现故障了怎么办
UDP
特点
功能
TCP和UDP区别
JVM
内存结构
堆
堆内存中的数据是线程共享的吗
栈
如何排查内存泄漏
内存溢出现象
堆/Perm 区不断增长
每次FullGC后, 堆/Perm 区在慢慢的增长
Minor GC(Yang GD)和Full GC
排查内存泄漏过程
jmap命令
命令:jmap -heap pid 展示pid的整体堆信息
命令: jmap -histo pid 展示class的内存情况
dump 将内存使用的详细情况输出到文件
命令: jmap -dump:live,format=b,file=a.log pid
分析 dump 文件和堆占用情况
定位具体的类和相关代码的调用过程
调优
调优命令
调优工具
为什么会出现脏读?
你说`volatile`可以避免指令重排,能否解释下什么是指令重排
知道`happens-before`吗,能否简单解释下
数据结构
数组
链表
单向链表
单向循环链表
双向链表
双向循环链表
JDK源码
集合
HashMap
1.7链表头插-1.8改为尾插
扩容机制
扩容
为什么1.8扩容的时候为啥一定必须是2的多少次幂
`ReHash`重哈希
看过`HashMap`源码吗,介绍下你了解的`HashMap`
能否解释下什么是`Hash`碰撞?常见的解决办法有哪些,`hashmap`采用哪种方法
`HashMap`底层是 数组+链表+红黑树,为什么要用这几类结构呢
为啥选择红黑树而不用其他树,比如二叉查找树,为啥不一直开始就用红黑树,而是到`8`的长度后才变换
put核心流程
为什么采用 哈希码 与运算(&) (数组长度-1) 计算数组下标
1.8HashMap为什么在计算数组下标前,需对哈希码进行二次处理:扰动处理
HashMap什么情况下出现链表环
为什么在JDK1.8中进行对HashMap优化的时候,把链表转化为红黑树的阈值是8,而不是7或者不是20呢
如何判断链表有环
为什么HashMap默认设置为16
ConcurrentHashMap
了解`ConcurrentHashMap`吗?为什么性能比`hashtable`高,说下原理?
`jdk1.7`和`jdk1.8`里面`ConcurrentHashMap`实现的区别有没了解
说下`ConcurrentHashMap`的`put`的核心逻辑(`JDK8`以上版本)
LinkedList
查询效率高
LinkedHashMap
链表的排序选择
插入顺序
访问顺序
LRU缓存
使用场景
String中HashCode方逻辑
String中hashcode方法为什么选择31这个质数而不选择更大的质数呢
hashcode值溢出
框架
Spring
IOC容器Inversion of Control,即“控制反转”
IOC容器源码
new AnnotationConfigApplicationContext(Cap12MainConfig.class):
1. 由于AnnotationConfigApplicationContext extends GenericApplicationContext
BeanDefinitionPostProcessor:
1. bean的后置处理器;
2. 实现这个接口的bean自定义bean加载数据;
3. 注册其他bean;
4. 先执行postProcessBeanDefinitionRegistry,后执行postProcessBeanFactory
refresh()
invokeBeanFactoryPostProcessors(beanFactory)
invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry)
postProcessBeanDefinitionRegistry(registry)
postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry):
1. 自定义的方法;
postProcessBeanFactory(beanFactory)
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory):
1. 自定义方法
BeanFactoryPostProcessor:
1. bean的后置处理器;
2. 实现这个接口的bean自定义bean加载数据;
refresh()
invokeBeanFactoryPostProcessors(beanFactory)
invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false):
1. 在beanFactory中找到所有BeanFactoryPostProcessor类型的组件;
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory)
postProcessBeanFactory(beanFactory)
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory):
1. 创建业务bean时,会调用自己实现的postProcessBeanFactory方法;
refresh()
prepareRefresh():
1. 刷新容器前的预处理;
initPropertySources():
1. 初始化一些属性设置;子类自定义个性化的属性设置方法
getEnvironment().validateRequiredProperties():
1. 检验属性的合法性等
this.earlyApplicationEvents = new LinkedHashSet<>():
1. 保存容器中的一些早期的事件
obtainFreshBeanFactory():
1. 获取beanFactory实例;
2. 创建的beanFactory好多属性没有值,只有一些默认的值;
refreshBeanFactory():
1. 刷新或创建beanFactory
getBeanFactory():
1. 将刚生成的beanFactory返回(空的beanFactory)
prepareBeanFactory(beanFactory):
1. beanFactory预准备工作
beanFactory.setBeanClassLoader(getClassLoader()):
1. 设置BeanFactory的类加载器
beanFactory.setBeanExpressionResolver:
1. 支持相关的表达式语言的解析
beanFactory.ignoreDependencyInterface:
1. 设置忽略的自动装配接口
beanFactory.registerResolvableDependency:
1. 注册可以解析的自动装配:我们能直接在任何组件中自动注入 BeanFactory ApplicationContext
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)):
1. 添加监听检测的处理器
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)):
1. 注册环境变量相关bean
postProcessBeanFactory(beanFactory):
1. BeanFactory准备工作完成后进行的后置处理器工作;
2. 通过子类重写这个方法来在BeanFactory创建并预准备完成以后进一步的设置;至此BeanFactory创建和预准备完成
invokeBeanFactoryPostProcessors(beanFactory):
1. 执行BeanFactoryPostProcessor后置处理器方法
2. 自定义实现两个接口BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor;
3. 先执行`BeanDefinitionRegistryPostProcessor`;
4. 优先执行实现了`PriorityOrdered`的处理器;
5. 获取处理器bean对象;
initMessageSource():
1. 标签国际化资源,初始化messgeresource组件(国际化功能:消息解析,消息绑定)
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)):
1. 判断容器中是否有messageSource的ID,类型是MessageSource组件;
new DelegatingMessageSource():
1. 如果没有MessageSource组件就会创建并注册到IOC容器中;
registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource):
1. 注册MessageSource组件;
addSingleton(beanName, singletonObject)
this.singletonObjects.put(beanName, singletonObject):
1. new ConcurrentHashMap<>(256)创建的单实例对象放到ConcurrentHashMap中
initApplicationEventMulticaster():
1. 初始化事件派发器
getBeanFactory():
1. 获取beanFactory;
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)):
1. 判断有没有applicationEventMulticaster对象;
new SimpleApplicationEventMulticaster(beanFactory):
1. 创建事件派发器;
registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster):
1. 注册到容器中;
onRefresh():
1. 留给子容器(子类):子类可以重写这个方法,在容器刷新的时候自定义逻辑;
registerListeners():
1. 给容器中将所有项目里的ApplicationListener注册进来;
getApplicationEventMulticaster().multicastEvent(earlyEvent):
1. 事件派发;
finishBeanFactoryInitialization(beanFactory):
1. 给容器中将所有项目中单实例bean(非懒加载)初始化;
beanFactory.preInstantiateSingletons():
1. 单实例bean(非懒加载)初始化;
getMergedLocalBeanDefinition(beanName):
1. 获取bean的定义信息,依次进行创建和初始化;
getBean(beanName)
doGetBean(name, null, null, false)
getSingleton(beanName):
1. 先获取map缓存中保存的实例bean;
markBeanAsCreated(beanName):
1. 标记当前bean已经被创建了;
this.alreadyCreated.add(beanName):
1. 进行标记;
mbd.getDependsOn():
1. 获取当前bean依赖的其他bean,如果存在就从容器中获取依赖的bean;
createBean(beanName, mbd, args)
resolveBeforeInstantiation(beanName, mbdToUse):
1. 让BeanPostProcessor尝试返回一个代理对象;
doCreateBean(beanName, mbdToUse, args)
createBeanInstance(beanName, mbd, args):
1. 创建bean实例返回bean包装类型;
populateBean(beanName, mbd, instanceWrapper):
1. bean属性赋值;
if (bp instanceof InstantiationAwareBeanPostProcessor):
1. 后置处理器的处理;
postProcessAfterInstantiation(bw.getWrappedInstance(), beanName):
1. 调用后置处理器对bean进行定制处理;
applyPropertyValues(beanName, mbd, bw, pvs):
1. 对bean设置值;
initializeBean(beanName, exposedObject, mbd):
1. 前后处理器执行的地方,aop动态代理增强入口;
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):
1. bean初始化前置处理器;
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):
1. bean初始化后置处理器;
`finishRefresh()`
后置处理器
`SpringIOC`源码以及后置处理器如何工作的
`Spring`中有哪些后置处理器
容器创建对象的三种方式
默认的构造方法
静态工厂方法
实例工厂方法
Spring Bean的声明周期
DI-Dependency Injection,即“依赖注入”
循环依赖
检测是否存在循环依赖
`Spring`是如何解决循环依赖的
AOP面向切面编程
AOP源码分析
org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class<?>...)
refresh()
registerBeanPostProcessors(beanFactory):
后置处理器的创建,这些处理器用于拦截其他bean的创建。重点关注AnnotationAwareAspectJAutoProxyCreator后置处理器的创建
registerBeanPostProcessors(beanFactory, this):
1. 先获取ioc容器已经定义了的需要创建对象的所有BeanPostProcessor,并创建;
2. 优先注册实现了PriorityOrdered接口的BeanPostProcessor;
3. 再给容器中注册实现了Ordered接口的BeanPostProcessor;
4. 注册没实现优先级接口的BeanPostProcessor;
5. 创建好
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
getBean(ppName, BeanPostProcessor.class)
doGetBean(name, requiredType, null, false)
markBeanAsCreated(beanName)
createBean(beanName, mbd, args):
创建bean
resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd):
1. 在这里看出AOP核心处理器AnnotationAwareAspectJAutoProxyCreator
beanName: org.springframework.aop.config.internalAutoProxyCreator
type:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
applyBeanPostProcessorsBeforeInstantiation(targetType, beanName):
1. spring对已经要定义的bean进行前置处理
2. AOP核心处理器bean的前置处理器,基本都会返回空,拿不到
postProcessBeforeInstantiation(beanClass, beanName):
1. 在这个方法前打断点,进入具体实现方法
doCreateBean(beanName, mbdToUse, args)
createBeanInstance(beanName, mbd, args):
1. bean的创建
populateBean(beanName, mbd, instanceWrapper):
1. 初始化beanset值
initializeBean(beanName, exposedObject, mbd):
1. bean的初始化
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):
1. 普通bean的前置处理器
invokeInitMethods(beanName, wrappedBean, mbd):
1. 初始化bean
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):
1. 普通bean的后置处理器
2. AOP核心处理器bean的后置处理器
3. 拿到所有通知方法
4. 创建增强的动态代理对象
postProcessAfterInitialization(result, beanName):
1. 在此方法前打断点,找到beanProcessor=AnnotationAwareAspectJAutoProxyCreator类型bean,进入该方法
wrapIfNecessary(bean, beanName, cacheKey):
1. 获取增强的方法
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)):
1. 重组增强方法
getProxy(getProxyClassLoader())
createAopProxy()
getProxy(classLoader)
org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
创建实现Ordered接口的bean(AnnotationAwareAspectJAutoProxyCreator):
1. 开启@EnableAspectJAutoProxy注解时,会把AOP核心处理器对象添加到IOC容器中
getBean(ppName, BeanPostProcessor.class)
doGetBean(name, requiredType, null, false)
markBeanAsCreated(beanName)
createBean(beanName, mbd, args):
创建bean
resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd):
1. 在这里看出AOP核心处理器AnnotationAwareAspectJAutoProxyCreator
beanName: org.springframework.aop.config.internalAutoProxyCreator
type:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
applyBeanPostProcessorsBeforeInstantiation(targetType, beanName):
1. spring对已经要定义的bean进行前置处理
2. AOP核心处理器bean的前置处理器,基本都会返回空,拿不到
postProcessBeforeInstantiation(beanClass, beanName):
1. 在这个方法前打断点,进入具体实现方法
doCreateBean(beanName, mbdToUse, args)
createBeanInstance(beanName, mbd, args):
1. bean的创建
populateBean(beanName, mbd, instanceWrapper):
1. 初始化beanset值
initializeBean(beanName, exposedObject, mbd):
1. bean的初始化
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):
1. 普通bean的前置处理器
invokeInitMethods(beanName, wrappedBean, mbd):
1. 初始化bean
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):
1. 普通bean的后置处理器
2. AOP核心处理器bean的后置处理器
3. 拿到所有通知方法
4. 创建增强的动态代理对象
5. AnnotationAwareAspectJAutoProxyCreator-bean创建完成
finishBeanFactoryInitialization(beanFactory):
1. 创建业务非懒加载单实例bean,以Calculator类为例
preInstantiateSingletons()
getBean(beanName)
doGetBean(name, null, null, false)
markBeanAsCreated(beanName)
createBean(beanName, mbd, args)
resolveBeforeInstantiation(beanName, mbdToUse)
doCreateBean(beanName, mbdToUse, args)
createBeanInstance(beanName, mbd, args):
1. bean的创建
populateBean(beanName, mbd, instanceWrapper):
1. 初始化beanset值
initializeBean(beanName, exposedObject, mbd):
1. bean的初始化
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName):
1. 普通bean的前置处理器
invokeInitMethods(beanName, wrappedBean, mbd):
1. 初始化bean
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName):
1. 普通bean的后置处理器
2. AOP核心处理器bean的后置处理器
3. 拿到所有通知方法
4. 创建增强的动态代理对象
5. AnnotationAwareAspectJAutoProxyCreator-bean创建完成
postProcessAfterInitialization(result, beanName):
1. 在此方法前打断点,找到beanProcessor=AnnotationAwareAspectJAutoProxyCreator类型bean,进入该方法
wrapIfNecessary(bean, beanName, cacheKey):
1. 获取增强的方法
getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null)
findEligibleAdvisors(beanClass, beanName)
findCandidateAdvisors()
addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()):
1. 找到切面类的所有通知方法
2. 切面表达式
3. 切入点等信息
findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName):
1. 匹配bean类型是否包含切面信息,也就是判断bean是否可以使用这些切面信息
sortAdvisors(eligibleAdvisors):
1. 切面类的通知方法倒序排序,目的是定义执行顺序
createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)):
1. 重组增强方法
getProxy(getProxyClassLoader())
createAopProxy()
getProxy(classLoader)
org.springframework.aop.framework.CglibAopProxy#getProxy(java.lang.ClassLoader)
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept:
1. aop代理对象执行业务处理时的处理方法
2. 拦截目标的执行
this.advised.getTargetSource():
1. 获取目标对象
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)
执行器链:this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass)
chain.isEmpty() && Modifier.isPublic(method.getModifiers()):
1. 如果没有拦截器链,直接执行目标方法;拦截器链(每一个通知方法又被包装为方法拦截器,利用MethodInterceptor机制)
new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy):
1. 如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链等信息传入创建一个 CglibMethodInvocation 对象
2. 通过创建动态代理类对象调用业务方法
proceed():
1. 每个拦截器处理对应的方法
2. 如果没有拦截器执行执行目标方法,或者拦截器的索引和拦截器数组-1大小一样(指定到了最后一个拦截器)执行目标方法;
3. 链式获取每一个拦截器,拦截器执行invoke方法,每一个拦截器等待下一个拦截器执行完成返回以后再来执行;拦截器链的机制,保证通知方法与目标方法的执行顺序;
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex):
1. 拿到拦截点对象
invoke(this):
1. 会调用各自拦截器的invoke方法
2. MethodBeforeAdviceInterceptor@2234为最后一个拦截器,进入invoke方法后会执行执行目标方法
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()):
1. 拿到目标方法的参数等信息,并执行@Before("pointCut()")注解的方法中的具体业务逻辑;
mi.proceed():
1. 执行目标方法
invokeJoinpoint():
1. 倒叙执行拦截器的invoke方法;
2. 执行源目标方法;
this.methodProxy.invoke(this.target, this.arguments)
声明式事务源码分析:
1. @EnableTransactionManagement开启事务管理功能;
2. 该注解会利用org.springframework.transaction.annotation.TransactionManagementConfigurationSelector类导入两个组件:
AutoProxyRegistrar
ProxyTransactionManagementConfiguration
refresh()
invokeBeanFactoryPostProcessors(beanFactory):
1. 导入组件
2. 动态代理创建组件和AOP的AnnotationAwareAspectJAutoProxyCreator核心组件创建方式一样;
AutoProxyRegistrar组件:
1. 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件,该组件利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用
registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry)
registerAutoProxyCreatorIfNecessary(registry)
registerAutoProxyCreatorIfNecessary(registry, null)
registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source):
1. 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件
registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition)
ProxyTransactionManagementConfiguration组件,创建方式同上
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration#transactionAdvisor:
1. 给容器中注入事务增强器BeanFactoryTransactionAttributeSourceAdvisor;
1. 给容器中注入事务拦截器TransactionInterceptor
org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor:
1. 事务增强器
transactionAttributeSource():
1. 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
org.springframework.transaction.interceptor.TransactionAttributeSource:
1. 解析事务注解类,包含事务信息
org.springframework.transaction.interceptor.TransactionInterceptor:
1. 事务拦截器;
2. 保存了事务属性信息,事务管理器;
3. 是一个 MethodInterceptor
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept:
1. 执行拦截器链,执行业务方法时被拦截,进入此方法
proceed()
org.springframework.transaction.interceptor.TransactionInterceptor#invoke
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
getTransactionAttributeSource():
1. 获取事务相关属性
determineTransactionManager(txAttr):
1. 获取事务管理器组件,如果事先没有添加指定任何transactionmanger最终会从容器中按照类型获取一个PlatformTransactionManager;
methodIdentification(method, targetClass, txAttr):
1. 获取目标方法
invocation.proceedWithInvocation()
invokeJoinpoint()
this.methodProxy.invoke(this.target, this.arguments)
fci.f1.invoke(fci.i1, obj, args):
1. 执行目标方法
2. 执行slq
completeTransactionAfterThrowing(txInfo, ex):
1. 异常捕获
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()):
1. 事务回滚
cleanupTransactionInfo(txInfo):
1. 清空事务信息
commitTransactionAfterReturning(txInfo):
1. 提交sql
spring为什么默认使用JDK动态代理
Spring IOC存储的实例为什么默认是单实例的
并发情况下Spring Bean是否安全
自动装配注解
主要有哪些模块
spring常用注入bean方式
MyBatis
数据库
关系型数据库
MySQL
相关概念
主键
外键
缺点
优点
使用
脏读
不可重复读
幻读
事务的四大特性
索引
mysql常用的功能索引有哪些
索引方法
B+Tree
特点
HASH
特点
数据索引类型
FULLTEXT
使用索引的优缺点有哪些,使用应该注意些什么
聚集索引
非聚集索引(辅助索引)
物理索引
逻辑索引
举例说明各种索引
覆盖索引
左侧索引原则
为什么索引能提高查询速度
字符集
UTF8Bmb4区别
应用
select * 效率低原理
说下执行顺序 select、where、from、group by、having、order by
count(*),count(1),count(id)
幻读和不可重复读的区别
事务隔离级别
Read Uncommitted(未提交读,读取未提交内容)
Read Committed(提交读,读取提交内容)
Repeatable Read(可重复读,mysql默认的事务隔离级别)
Serializable(可串行化)
数据存储引擎
InnoDB
MyISAM
innodb和myisam有什么区别
字符串类型字段
MySQL中的varchar和char有什么区别
时间类型字段
为什么timestamp只能到2038年
datetime和timestamp有什么区别
性能安全优化
一个商品表数据量过千万
针对线上的数据库,你会做哪些监控,业务性能 + 数据安全 角度分析
分区
适合场景
分表
垂直拆分
水平拆分
mysql -load data csv.file超大数据量迁移
MySQL日志
主从复制
你能画下流程图说下异步复制原理不
主从复制的目的有哪些
同步延迟问题
判断主从延迟工具
主从数据不一致
防止主从数据不一致
主从数据一致性解决方案
是否有做过主从一致性校验
pt-table-checksum怎么保证某个chunk的时候checksum数据一致性
主从延迟判断和避免
非关系型
Redis
分布式锁
SETNX(SET if Not eXists)
SETEX(原子操作, 将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位))
Lua脚本setnx、setex命令连用(原子操作)
RedisConnection实现分布式锁(高效获取锁方式-spring-data-redis-2.0.10.RELEASE.jar
锁设置超时时间,防止服务宕机,产生死锁
Lua脚本解锁原子操作
高可用
高可用概念
Redis读写分离是怎么做数据同步的
sentinel(哨兵模式)
分片重hash
新增主节点并给该节点分配hash槽、新增从节点、删除节点
一致性hash算法
twemproxy实现hash分片
redis持久化
RDB
AOF
redis过期key清除策略
微信红包实现原理
拆红包原理流程
分支主题
redisService.decr(redPacketName, 1);
redisService.decr(totalAmountName, randomAmount);
红包数量减一和红包金额进行原子操作
redis布隆过滤器
特点:只能保证容器中不存在和可能存在,不能保证容器中一定存在;
秒杀系统
前端资源放入CDN服务器
后端处理请求
判断秒杀是否已经开始
网管处理层过滤多余请求
skuId_access_sukid:
1. 接受请求数量-原子加;
skuId_count_sulid:
1. 商品总数量;
订单信息校验层
redis布隆过滤器:
1. 订单信息校验,如不可从复抢购;
被抢商品数量:
1. 记录skuId_booked_sukid用户抢到原子加一,最终skuId_booked_sukid=skuId_count_sulid(被抢商品数等于商品总数);
2. 防止超卖;
订单信息放入队列:
1. rocketmq防止订单数据丢失;
集群
Cluster
Sentinel(哨兵模式)
MongoDB
memcache
redis和memcache区别
分布式
分布式锁
Redisson工具实现分布式锁
分布式事务
消息最终一致性方案
SEATA解决分布式事务
分布式架构
微服务
微服务概念
SpringBoot
SpringCloud
SpringCloud核心组件
Netflix Eureka(服务发现)
如何解决Eureka Server不踢出已关停的节点的问题
关闭保护模式
配置开启健康检查,并按需配置续约更新时间和到期时间
Netflix Ribbon(客服端负载均衡)
Netflix Hystrix(断路器)
熔断
降级
Hystrix降级策略
隔离策略(用户解决雪崩效应)
服务熔断和降级关系
Netflix Zuul(服务网关)
Spring Cloud Config(分布式配置)
Feign
feign和RestTemplate区别
应用
使⽤中碰到的坑
Dubbo
SpringCloud和Dubbo区别
微服务的优缺点
优点
缺点
限流
中间件
RabbitMQ
什么是`RabbitMQ`
为什么要使用MQ
使用场景
相关概念
Broker
Exchange
Queue
Binding
Routing Key
vhost
Producer
Consumer
Channel(信道)
持久化(duration)
确认机制(ACK)
消息是如何发送的?
消息基于什么传输(传输协议)
TCP连接和信道之间的关系
为什么不使用`TCP`连接发送`AMQP`命令
`AMQP`消息路由组成关系
消息是如何路由的
`provider`生产消息发送方式有哪些
如何确保消息正确地发送至`RabbitMQ`?如何确保消息接收方消费了消息?如何保证消息一致性的?
发送方确认模式
接收方确认机制
消息一致性特殊场景
避免重复投递
避免重复消费
消息丢失
provider
consumer
实现顺序消息
消息是怎么发送的?
如何分发消息的
高可用
MQ镜像集群模式
应用
消息模式
`simple`模式
`work`工作模式(资源的竞争)
`publish`/`subscribe`发布订阅(共享资源)
`routing`路由模式
`topic`主题模式(路由模式的一种)
`RPC`模式
模式比较
`simple`和`work`消息模式区别
消息队列
为什么要使用消息队列
各种消息队列特点
发送消息方式和比较
什么是延迟消息和使用场景
怎么实现顺序消息
避免重复消费
消息可靠性传输
消息发生大量堆积应该怎么处理
zookepper
功能
zookeeper 的通知机制
redis
分布式锁redisson
收藏
收藏
0 条评论
下一页