项目完成总结
项目整体框架是项目组其他大佬来搭建的,我在其基础上完成相关功能的开发,现在在这里总结一下,作为记录。
一 学习阿里的完善的开发习惯
从学习往实战过渡,有很多开发细节需要注意,为了尽量去避免一些不必要的错误和BUG,我们在设计系统的时候就要深入考虑:
在这里附上阿里的开发手册:阿里巴巴《Java 开发手册》嵩山版
- 异常处理 ,对可能出现异常的地方进行异常处理;
易踩坑点:1.Java 类库中定义的可以通过预检查方式规避的 RuntimeException 异常不应该通过catch 的方式来处理,比如: NullPointerException , IndexOutOfBoundsException 等等。说明: 无法通过预检查的异常除外,比如,在解析字符串形式的数字时,可能存在数字格式错误,不得不通过 catch NumberFormatException 来实现。2.不要在 finally 块中使用 return 。说明: try 块中的 return 语句执行成功后,并不马上返回,而是继续执行 finally 块中的语句,如果此处存在 return 语句,则在此直接返回,无需丢弃掉 try 块中的返回点。3. 异常 捕获后 不要用来做流程控制,条件控制。说明: 异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。4. 事务场景中,抛出异常被 catch 后,如果需要回滚,一定要注意手动回滚事务。
- 版本 无论是JDK还是其他一些工具的版本,应该保持一致,避免版本不同带来的问题;.
- 新特性 我们在工作的时候也是需要不断的学习的,善于使用一些技术的新特性可以大大地降低工作的复杂度和提升工作效率;
我在项目中使用了 JDK8 的新特性,使用lambda表达式+mybatis-plus的方式简化了代码,大大提高了代码的可读性
- 分布式 在进行系统设计的时候就必须考虑这个系统是往哪个方向设计,如果设计成分布式的,那么代码的设计就需要体现出模块化的思想,比如像@Cacheable这种的缓存注解就不能使用了,可以使用Redis来替代;
- 配置化 系统中的一些配置变量要统一写到application配置文件中;
- 日志 日志使用@slf4j,便于调试和测试或者其他时候对操作的记录和查看。
- swagger 在前后端分离的时候,前后端的连接就需要接口文档了,swagger就可以作为一个可测试的动态接口文档,swagger的配置和信息需要后端在代码中体现。
- Apifox 同样是前后端分离的情况下,后端对于接口的测试工具,是接口管理、开发、测试全流程集成工具,定位 Postman + Swagger + Mock + JMeter 相比Postman更优秀
- 设计模式 23款设计模式
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
还有并发型模式和线程池模式
- 线程安全 线程安全的类选择和数据库的类型选择都很重要。
二 编码之前的需求分析(流程图)
读书笔记总结
我读的是深入理解JVM虚拟机,目前读到了第7章
从中我总结了一部分笔记:
在JDK11之前,OracleJDK中还会存在一些OpenJDK中没有的、闭源的功能。但在JDK11中,我们可以认为OpenJDK和OracleJDK代码实质上已经完全一致。
Java虚拟机的特点
- 一次编译,到处运行
- 自动内存管理
- 自动垃圾回收功能
JVM的位置
JVM是运行在操作系统之上的,它与硬件没有直接的交互
Java虚拟机运行时数据区
其中
方法区和堆是多个线程共享的
虚拟机栈、本地方法栈和程序计数器(pc寄存器)是线程私有的内存。
其中:
- 程序计数器:当前线程所执行的字节码的行号指示器,用于记录正在执行的虚拟机字节指令地址,线程私有。
- 虚拟机栈:存放基本数据类型、对象的引用、方法出口等,线程私有。
- Native 方法栈: 和虚拟栈相似,它们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务
- Java堆: Java内存最大的一块,所有对象实例、数组都存放在Java堆,也是GC回收的地方,是线程共享的。
- 方法区: 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。(即永久带)
总结:
Native 方法栈保存非Java的操作
pc寄存器保存程序执行的步骤
方法区保存的是类的数据
堆保存的是类的实例
对象的创建
- 在常量池中定位,检查是否已经被加载、解析和初始化过
- 如果没有,虚拟机会分配新内存。在分配内存中,指针的移动也不是线程安全的。可以尝试:
- 虚拟机采用CAS和失败重试的方式
- 采用线程预分配内存
- 设置对象头信息,标注是哪个对象的实例、类的元数据信息、对象的hash码、GC分代信息等
- 执行<init>方法,根据程序员意愿进行初始化
对象的内存布局
- 对象在内存中存储的布局可以分为3块区域:对象头、实例数据、对齐填充
- 对象头:用于存储运行时数据,包括HashCode、年龄代、线程持有的锁、偏向线程ID、偏向时间
- 实例数据:存储对象的有效信息,包括继承的信息
- 对齐数据:不是必然存在的,没有特别的含义,主要起着补齐8字节的整数倍的作用
垃圾回收算法
1、标记清除算法:最基本的垃圾回收机制,
缺点:
效率不高,会产生大量空间碎片。
2、复制算法:绝大多数使用的算法,实现简单,运行高效,缺点:
会分担出一部分内存空间默认是8:1
3、复制收集算法对对象存活率较高,内存较小的系统不试用。(应用于新生代)
4、标记整理:标记出存活的对象,然后向一端移动。
5、分代收集算法:不同代采用不同等垃圾手机机制。新生代中存活量较多,采用复制算法;老年代存活率较高,内存较小,采用标记清除或者标记整理。
6、虚拟机采用根可达算法算出对象是否需要被销毁。
收集器
1、Serial收集器:是一个单线程收集器,使用期间,会停止其他工作。但是简单高效,适合非常小内存的新生代中使用,执行时间控制在最多100ms以内。新生代采用复制算法,老年代采用标记整理算法。
2、ParNew收集器:Serial收集器的多线程版本,且只有它和Serrial能与CMS收集器配合工作。
3、并行:多个人同时打扫房间卫生;并发:打扫卫生的同时,切换工作去做饭。
4、Parallel Scavenge:新生代复制算法收集器,多线程。注重CPU的吞吐量的收集器。
5、Serial Old:老年代标记整理算法,单线程。作为CMS收集器的兜底方案使用。
6、Parallel Old:标记整理算法,多线程,同Parallel一样,吞吐量优先。
7、CMS(Concurrent Mark Sweep):最短回收停顿为目标的收集器,重视服务器端的响应速度。
虚拟机的类加载机制
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。
验证、准备、解析统称为连接。
虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。
- 加载:加载一段二进制的输入流,你可以自定义类加载器。当new一个对象时候,子类加载的时候会加载父类。
- 连接:
- 验证:检验加载内容的合法性;
- 准备,讲静态变量在方法区中开辟空间,赋值为0或null;
- 解析:将类由符号引用替换为直接引用。
- 初始化:开始调用构造方法,赋值,构造是有锁的,只能单线程执行。
- 类加载器:双亲委派。