源码部分的解析基于
jdk8
一份学习笔记,巩固知识。同时期望能帮我找到一份薪水高、体面的工作。
- Java 中的八种基本数据类型,以及它们的封装类
- switch 能否用 String 做参数
- equals 与 == 的区别
- Object 有哪些共用的方法
- Java 的四种引用,强弱软虚,用到的场景
- HashCode 的作用
- ArrayList、LinkedList、Vector 的区别
- String、StringBuffer 与 StringBuilder 的区别
- Map、Set、List、Queue、Stack 的特点与用法
- HashMap 和 ConcurrentHashMap 的区别,HashMap 的底层源码
- TreeMap、HashMap、LinkedHashMap 的区别
- Collection 包结构,与 Collections 的区别
- try catch finally, try 里面有 return, finally 还执行吗
- Exception 与 Error 包结构。OOM 你遇到过哪些情况, SOF 你遇到过哪些情况
- 面向对象的特征和含义
- Override 和 Overload 的含义与区别
- interface 与 abstract 的区别
- static class 和 non static class 的区别
- Java 多态的实现原理
- 线程同步的方法:sychronized、lock、reentrantLock 等
- 锁的等级:方法锁、对象锁、类锁
- 写出生产者消费者模式
- Concurrent 包中的其他东西: ArrayBlockingQueue,CountDownLatch 等
- wait() 和 sleep() 的区别
- foreach 与正常 for 循环效率对比
- Java IO 与 NIO
- 反射的作用与原理
- 泛型常用特点,List< String > 能否转换成 List< Object >
- 解析 XML 的几种方式的原理与特点:DOM、SAX、PULL
- Java 与 C++ 对比
- Java1.7 与 1.8 新特性
- 常用的设计模式:单例、工厂、适配器、责任链、观察者等
- JNI ( Java Native Interface ) 的使用
基于 jdk 1.8 分析
-
Map 接口典型实现类源码分析
-
List 接口典型实现类源码解析
- ArrayList 源码解析
- LinkedList 源码解析
-
Set 接口典型实现类源码解析
- HashSet 源码解析
- Hashtable 源码解析
-
线程池的阻塞队列
-
创建线程的两种方法:Thread 与 Runable见线程池实现原理(三种实现线程的方式)-
继承 Thread 类,实现 run 方法,无返回值
public class ThreadDemo1 extends Thread { @Override public void run() { super.run(); System.out.println("当前线程名称:" + this.getName()); } }
-
实现 Runable 接口 ,实现 run 方法,无返回值
public class ThreadDemo2 implements Runnable { @Override public void run() { System.out.println("第二种方式实现线程:" + Thread.currentThread().getName()); } }
-
实现 Callable 接口,实现 call 方法,有返回值 Future 类型
public class ThreadDemo3 implements Callable<String> { @Override public String call() throws Exception { System.out.println("第三种线程名称:" + Thread.currentThread().getName()); return "success"; } }
-
- JVM 内存管理
- 内存模式以及分区,需要详细到每个区放什么
- 堆里面的分区:Eden、survival from to、老年代各自的特点
- 对象的创建方法、对象的内存分配、对象的访问定位
- GC 的两种判定方法:引用计数与引用链
- GC 的三种收集方法:标记清除、标记整理、复制算法的原理与特点?分别用在什么地方?如果让你优化收集方法,有什么思路?
- GC 收集器有哪些? CMS 收集器与 G1 收集器的特点
- Minor GC 与 Full GC 分别在什么时候发生?
- 几种常用的内存调试工具:jmap、jstack、jconsole
- 类加载的五个过程:加载、验证、准备、解析、初始化
- 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader
- 分配:静态分派与动态分派
- 进程和线程的区别
- 死锁的必要条件,怎么处理死锁
- Window 内存管理方式:段存储、页存储、段页存储
- 进程的几种状态
- IPC 几种通信方式
- 什么是虚拟内存
- 虚拟地址、逻辑地址、线性地址、物理地址的区别
- OSI 与 TCP/IP 各层的结构与功能,都有那些协议
- TCP 与 UDP 的区别
- TCP 报文结构
- TCP 的三次握手与四次挥手过程,各个状态名称与含义, TIMEWAIT 的作用
- TCP 拥塞控制
- TCP 滑动窗口与回退 N 帧协议
- Http 的报文结构
- Http 的状态码含义
- Http Request 的几种类型
- Http1.1 和 Http1.0 的区别
- Http 怎么处理长连接
- Cookie 与 Session 的作用与原理
- 电脑上访问一个网页,整个过程是怎样的:DNS、HTTP、TCP、OSPF、IP、ARP
- Ping 的整个过程,ICMP 报文是什么
- C/S 模式下使用 socket 通信,几个关键函数
- IP 地址分类
- 路由器与交换机区别
-
对列和栈,出栈与入栈
-
链表的删除、插入、反向
-
字符串操作
-
Hash 表的 hash 函数,冲突解决方法有哪些
-
各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理。平均时间复杂度、最坏时间复杂度、空间复杂度以及是否稳定
-
快排的 partition 函数与归并的 Merge 函数
-
对冒泡与快排的改进
-
二分查找,与变种二分查找
- 二分查找-本地文档,比较简单,没有放在博客上
- 变种二分查找
-
二叉树、B+ 树、 AVL 树、红黑树、哈弗曼树
-
二叉树遍历
- 前序遍历
- 中序遍历
- 后序遍历
-
二叉树的递归与非递归写法,层序遍历算法
-
图的 BFS(广度优先) 与 DFS(深度优先) 算法,最小生成树 prim 算法与最短路径 Dijkstra(单源点最短路径) 算法
-
KMP 算法
-
排列组合问题
-
动态规划、贪心算法、分治算法
-
大数据处理:类似 10 亿条数据找出最大的 1000 个数
-
Redis
- Redis 事务
- Redis 持久化策略
- [Redis 基本数据类型](06-数据库/redis/redis 的基本概念.md)
- [Redis 主从同步,哨兵,集群模式](06-数据库/redis/redis 主从复制(Sentinel 哨兵模式)和集群模式(Redis-Cluster).md)
-
Mongodb
-
Mysql
- Spring &SpringBoot&SpringMVC
-
传统的 SpringMVC 初始化流程
- 通过 SpringServletContainerInitializer 来负责对容器启动时相关组件进行初始化
- 到底要初始化哪些组件则是通过 Servlet 规范中所提供的组件 HandlesTypes 来指定的
- 在 SpringServletContainerInitializer 中,其 HandlesTypes 注解则明确指定为了 WebApplicationInitializer.class 类型
- 在 SpringServletContainerInitializer 的 onStartup 方法中,则主要是完成了一些验证与组件装配的工作
- 在 SpringServletContainerInitializer 的 onStartup 方法中,由于某些容器并未遵循 Servlet 规范,导致虽然明确指定了 HandlesTypes 注解的具体类为 WebApplicationInitializer.class 类型,但还是可能会存在将一些非法类型传递过来的情况;所以该方法还对传递进来的具体类型做了细致的判断,只有符合条件的类型才会被纳入到 List 集合中。
- 当以上的判断完成之后,List 就是接下来需要进行初始化的组件了。
- 最后通过遍历 List 列表取出其中的每一个 WebApplicationInitializer 对象,调用这些对象的 onStartup 方法,完成组件的启动初始化工作。
总结一下: SpringServletContainerInitializer 在整个初始化过程中,其扮演的角色实际上是委托或是代理的角色,真正完成初始化工作的依旧是一个个的 WebApplicationInitializer 实现类。
现代的 SpringBoot 应用容器初始化过程:
- 对于 SpringBoot 应用来说,它并未使用 SpringServletContainerInitializer 来进行容器的初始化,而是使用了 TomcatStarter 进行的初始化
- TomcatStarter 存在三点因素使得它无法通过 SPI(Service Provider Interface)机制来进行实例化;它没有不带参数的构造方法;他的声明并非 public;其所在的 jar 包并没有 META-INF.services 目录,当然也就不存在名为 javax.servlet.ServletContainerInitializer 的文件了。
- 综上,TomcatStarter 并非通过 SPI 机制进行的查找与实例化。
- 本质上,TomcatStarter 是通过 SpringBoot 框架 new 出来的。
- 与 SpringServletContainerInitializer 类似,TomcatStarter 在容器的初始化过程中也是扮演者一个委托或者是代理的角色,真正完成初始化工作实 际上是由它所持有的 ServletContextInitializer 的 onStartup 方法来完成的。
关于 Servlet3.0 的一些重要特性 1.
关于传统的 SpringMVC 和现代的 SpringBoot 应用组件之间的对应关系
-
SpringServletContainerInitializer 对应于 TomcatStarter
-
WebApplicationInitializer 对应于 ServletContextInitializer
-
Spring 基本使用
build.gradle
dependencies { compile ( "org.springframework:spring-core:5.2.5.RELEASE", "org.springframework:spring-aop:5.2.5.RELEASE", "org.springframework:spring-context:5.2.5.RELEASE", "org.springframework:spring-context-support:5.2.5.RELEASE", "org.springframework:spring-beans:5.2.5.RELEASE", "org.springframework:spring-orm:5.2.5.RELEASE", "org.springframework:spring-aspects:5.2.5.RELEASE", "org.springframework:spring-webmvc:5.2.5.RELEASE", "org.springframework:spring-jdbc:5.2.5.RELEASE", "org.springframework:spring-tx:5.2.5.RELEASE", "org.springframework:spring-instrument:5.2.5.RELEASE", ) }
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd"> <!-- 属性注入 --> <bean id="student" class="com.liqiwen.spring.bean.Student"> <property name="name" value="zhangsan"/> <property name="age" value="20"/> </bean> </beans>
测试方法
public static void main(String[] args){ //将 applicationContext.xml 配置文件转换成 Resource Resource resource = new ClassPathResource("applicationContext.xml"); //初始化默认的 BeanFactory //XMLBeanFactory 继承至 DefaultListableBeanFactory,已被废弃 DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory(); //Bean 定义读取器 BeanDefinitionReader BeanDefinitionReader = new XMLBeanDefinitionReader(defaultListableBeanFactory); //加载 Bean 定义 BeanDefinitionReader.loadBeanDefinitions(resource); //从容器中获取 Bean 对象 Student student = (Student) defaultListableBeanFactory.getBean("student"); } /** * 方式二 **/ public static void main(String[] args){ //准备容器 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) ac.getBean("student"); }
-
Spring Bean 对象加载过程
-
FactoryBean 和 BeanFactory 的区别
- FactoryBean 是一个工厂 Bean,本质还是一个 bean
- BeanFactory 是整个 IOC 容器的核心,里面维护了所有的 Bean 实例
-
SpringMVC 执行流程
-
SpringMVC 进行开发
web.xml //部署描述符 需要配置 Filter Listener Servlet 位于 WEB-INF 目录下 还需要配置 DispatchServlet 以及 ContextLoaderListener
-
-
Spring 中使用了哪些设计模式
- 工厂模式 BeanFactory
- 简单工厂模式(静态工厂方法) BeanFactory
- 代理模式,基于 Jdk 的动态代理和 cglib 代理(AOP)
- 观察者模式(事件和监听 ApplicationListener)
- 单例模式
- 模板方法模式(xxxTemplate)
- 适配器模式(Adapter)
-
SpringBoot
-
SpringBoot 使用 run as 启动和打包成 jar 文件使用 java -jar 启动有何不同?
使用类加载器不同 - 直接使用右键 run as 启动,使用的是 AppClassLoader 加载器(系统类加载器/或者应用类加载器) - 使用 java -jar test.jar 启动,使用的是 Spring 提供的自定义的类加载器 LaunchedURLClassLoader 加载器来加载
-
SpringBoot 打包后的目录结构
BOOT-INF classes //应用 classes 文件 lib // 依赖的 jar 包 META-INF MANIFEST.MF //清单文件,指定了 JarLauncher 和 Start-Class org springframework boot loader
SpringBoot 项目在启动的时候会去加载三个 spring.factories 文件,分别位于 auto-configure,spring-boot 以及 spring-beans 里面,将加载到的信息分别存放到 MutilValueMap 中。
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = cache.get(classLoader); if (result != null) { return result; } try { // FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories" Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) : ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION)); result = new LinkedMultiValueMap<>(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); for (Map.Entry<?, ?> entry : properties.entrySet()) { String factoryTypeName = ((String) entry.getKey()).trim(); for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) { result.add(factoryTypeName, factoryImplementationName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } }
Spring 获取主类是通过运行时期异常获取的
private Class<?> deduceMainApplicationClass() { try { // 获取堆栈信息 StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) { if ("main".equals(stackTraceElement.getMethodName())) { return Class.forName(stackTraceElement.getClassName()); } } } catch (ClassNotFoundException ex) { // Swallow and continue } return null; }
-
-
SpringCloud
-
Eureka 注册时配置文件
# 服务端配置文件 eureka: client: fetch-registry: false register-with-eureka: false service-url: ## 这里 idea 会提示 default-zone 这个字段,不要使用 default-zone 字段,客户端会无法注册上去 ## 这个地址是客户端向其注册的地址 defaultZone: http://localhost:10099/eureka/ instance: hostname: MyEurekaServer spring: application: name: Eureka-Server server: port: 10099
客户端配置文件
eureka: client: fetch-registry: true register-with-eureka: true ## 客户端注册地址,idea 会提示 service-url,不要使用 service-url,使用之后会导致客户端无法注册上去 serviceUrl: ## 同服务端类似 defaultZone: http://localhost:10099/eureka/ spring: application: name: Eureka-Client server: port: 8888
-
Robbin
-
Feign
- 可插拔的 HTTP 客户端实现
- 可插拔的编解码器
- 可对 HTTP 请求进行相应的 gzip 压缩
- 可设定压缩的阈值
- 自带负载均衡实现(内部实现了 Ribbon)
- 自带熔断器
- 请求日志详细信息展示
- 自带重试处理器
Feign 底层是通过 jdk 动态代理实现的,在运行期间生成代理对象。
-
Hystric
-
Zuul (服务网关)
-
GateWay(服务网关)
-
Config
-
消息总线
-
分布式链路追踪 Sleuth
-
zipkin
-
-
Dubbo
-
Mybatis
-
Zookeeper
-
Nginx
-
Nacos
1. 线程
- 如何使两个线程交叉打印?例如打印 hello。线程 1 打印 h,线程 2 打印 e,线程 1 打印 l,线程 2 打印 l,线程 1 打印 e。
- 解决方案参考:Object 对象的 wait 和 notify 方法
2. 集合
- 准备使用 HashMap 存储 1w 条数据,构造方法传入 1w 会触发扩容吗?传入 1k 呢?
- 解决方案参考这里