JAVA高级要求
项目情况
- 1.主要的职责
- 2.主要的贡献
- 3.解决的难点
- 4.心得
基础
数据结构算法
线性结构包括:数组,链表,队列,栈;
非线性结构包括:树,图,表;
多线程模型
Future模型、Fork&Join 模型、Actor消息模型、生产者消费者模型、Master-Worker模型。
Servlet原理
Servlet 容器作为一个独立发展的标准化产品,目前它的种类很多,如jetty、tomcat。
Tomcat 的容器分为四个等级,真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程。
1、Web Client 向Servlet容器(Tomcat)发出Http请求
2、Servlet容器接收Web Client的请求
3、Servlet容器创建一个HttpRequest对象,将Web Client请求的信息封装到这个对象中
4、Servlet容器创建一个HttpResponse对象
5、Servlet容器调用HttpServlet对象的service方法,把HttpRequest对象与HttpResponse对象作为参数传给 HttpServlet对象
6、HttpServlet调用HttpRequest对象的有关方法,获取Http请求信息
7、HttpServlet调用HttpResponse对象的有关方法,生成响应数据
8、Servlet容器把HttpServlet的响应结果传给Web Client
JDBC原理
JDBC是接口,而JDBC驱动才是接口的实现,没有驱动无法完成数据库连接!每个数据库厂商都有自己的驱动,用来连接自己公司的数据库。
JDBC中的核心类有:DriverManager、Connection、Statement,和ResultSet!
DriverManger(驱动管理器)的作用有两个:
l 注册驱动:这可以让JDBC知道要使用的是哪个驱动;
l 获取Connection:如果可以获取到Connection,那么说明已经与数据库连接上了。
Connection对象表示连接,与数据库的通讯都是通过这个对象展开的:
l Connection最为重要的一个方法就是用来获取Statement对象;
l Statement是用来向数据库发送SQL语句的,这样数据库就会执行发送过来的SQL语句
l void executeUpdate(String sql):执行更新操作(insert、update、delete等);
l ResultSet executeQuery(String sql):执行查询操作,数据库在执行查询后会把查询结果,查询结果就是ResultSet;
ResultSet对象表示查询结果集,只有在执行查询操作后才会有结果集的产生。结果集是一个二维的表格,有行有列。操作结果集要学习移动ResultSet内部的“行光标”,以及获取当前行上的每一列上的数据。
Spring特点
-
一、非侵入式编程
Spring框架的API不会再业务逻辑上出现,即业务逻辑是POJO(Plain Ordinary Java Object)。由于业务逻辑中没有Spring的API,所以业务逻辑可以从Spring框架快速的移植到其他框架。
-
二、容器
Spring作为一个容器,可以管理对象的生命周期、对象与对象之间的依赖关系。可以通过配置文件来定义对象,以及设置其他对象的依赖关系。
-
三、IoC
控制反转(Inversion of Control),即创建被调用的实例不是由调用者完成,而是由Spring容器完成,并注入调用者。
当应用IoC,一个对象依赖的其他对象会通过被动的方式传递进来,而不是这个对象自己创建或查找依赖对象,即,不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
-
四、AOP
面向切面编程,是一种编程思想,是面向对象编程OOP的补充。Spring提供面向对象编程的支持,允许通过分离应用的业务逻辑与系统级服务(日志和事务管理)进行开发。应用对象只实现他们应该做的(完成业务逻辑),并不负责其它的系统级关注点(日志或者事务的支持)。
可以把日志、安全、事务管理等服务理解成一个“切面”,把很多被业务逻辑反复使用的服务完全剥离出来,以达到复用。然后将“切面”动态的“织入”到业务逻辑中,让其享受此“切面”的服务。
中高级特性
并发包
集合包最常用的有Collection和Map两个接口的实现类,Colleciton用于存放多个单对象,Map用于存放Key-Value形式的键值对。
Collection中最常用的又分为两种类型的接口:List和Set,两者最明显的差别为List支持放入重复的元素,而Set不支持。
类加载机制
- 不可以自己写个String类,因为 根据类加载的双亲委派机制,会去加载父类,父类发现冲突了String就不再加载了;
- 加载类的时候,可以使用Java探针技术(JAVA agent)对类的字节码进行修改;
- 类加载器
启动类加载器,Bootstrap ClassLoader,加载JACA_HOME\lib,或者被-Xbootclasspath参数限定的类
扩展类加载器,Extension ClassLoader,加载\lib\ext,或者被java.ext.dirs系统变量指定的类
应用程序类加载器,Application ClassLoader,加载ClassPath中的类库
自定义类加载器,通过继承ClassLoader实现,一般是加载我们的自定义类
- 要创建用户自己的类加载器,只需要继承java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,即指明如何获取类的字节码流;
如果要符合双亲委派规范,则重写findClass方法(用户自定义类加载逻辑);要破坏的话,重写loadClass方法(双亲委派的具体逻辑实现)。
- 要创建用户自己的类加载器,只需要继承java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,即指明如何获取类的字节码流;
GC原理与调优
- Java 的内存管理实际上就是对象的管理,其中包括对象的分配和释放,对于程序员来说,分配对象使用new关键字;释放对象时,只要将对象所有引用赋值为null,让程序不能够再访问到这个对象,我们称该对象为"不可达的".GC将负责回收所有"不可达"对象的内存空间。
设计模式与框架源码
- 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
- 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
- 行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式遵循的原则有6个:
- 开闭原则(Open Close Principle)
对扩展开放,对修改关闭。
- 里氏代换原则(Liskov Substitution Principle)
只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
- 依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。
- 接口隔离原则(Interface Segregation Principle)
使用多个隔离的借口来降低耦合度。
- 迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
- 合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。
spring IOC AOP原理与优点
IOC
(1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转移是所谓反转。 对于Spring而言,就是由Spring来控制对象的生命周期和对象之间的关系;IoC还有另外一个名字——“依赖注入(Dependency Injection)”。从名字上理解,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,即由容器动态地将某种依赖关系注入到组件之中。
(2). 在Spring的工作方式中,所有的类都会在spring容器中登记,告诉spring这是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
(3). 在系统运行中,动态的向某个对象提供它所需要的其他对象。
(4). 依赖注入的思想是通过反射机制实现的,在实例化一个类时,它通过反射调用类中set方法将事先保存在HashMap中的类属性注入到类中。 总而言之,在传统的对象创建方式中,通常由调用者来创建被调用者的实例,而在Spring中创建被调用者的工作由Spring来完成,然后注入调用者,即所谓的依赖注入or控制反转。 注入方式有两种:依赖注入和设置注入; IoC的优点:降低了组件之间的耦合,降低了业务对象之间替换的复杂性,使之能够灵活的管理对象。
AOP
(1). AOP面向方面编程基于IoC,是对OOP的有益补充;
(2). AOP利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了 多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的 逻辑或责任封装起来,比如日志记录,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
(3). AOP代表的是一个横向的关 系,将“对象”比作一个空心的圆柱体,其中封装的是对象的属性和行为;则面向方面编程的方法,就是将这个圆柱体以切面形式剖开,选择性的提供业务逻辑。而 剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹,但完成了效果。
(4). 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
(5). Spring实现AOP:JDK动态代理和CGLIB代理 JDK动态代理:其代理对象必须是某个接口的实现,它是通过在运行期间创建一个接口的实现类来完成对目标对象的代理;其核心的两个类是InvocationHandler和Proxy。 CGLIB代理:实现原理类似于JDK动态代理,只是它在运行期间生成的代理对象是针对目标类扩展的子类。CGLIB是高效的代码生成包,底层是依靠ASM(开源的java字节码编辑类库)操作字节码实现的,性能比JDK强;需要引入包asm.jar和cglib.jar。 使用AspectJ注入式切面和@AspectJ注解驱动的切面实际上底层也是通过动态代理实现的。
(6). AOP使用场景:
Authentication 权限检查
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 延迟加载
Debugging 调试
logging, tracing, profiling and monitoring 日志记录,跟踪,优化,校准
Performance optimization 性能优化,效率检查
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务管理
另外Filter的实现和struts2的拦截器的实现都是AOP思想的体现。
数据库
复杂SQL与优化
- 2)利用redis加缓存
sql优化解决不了,那么我们可以用redis加缓存,在系统启动的时候就做一个数据的热处理提前加入到缓存中,以至于每次查询命中缓存。
- 3)读写分离,主从复制或者主主复制
缓存解决不了,我们可以做读写分离
- 4 )利用分区表
分区的表的原理就是把一张大表进行分区后,他还是一张表,不会变成二张表,但是他存放数据的区块变多了。 mysql的分表是真正的分表,一张表分成很多表后,每一个小表都是完正的一张表,比如user表按userid分表后就是user_01和user_02。分区表mysql有专门的语句做分区存储。
- 5)最后是分库分表
首先说一下oracle的分区表和表分区是不同的概念,其实就是oracle的分区表说的就是mysql的分区表,但是表分区说的就是mysql的分表操作,也就是我们所说的水平拆分。f分库分表也是我们所说的分库就是垂直拆分,分表就是水平拆分。
垂直拆分:把表按模块划分到不同数据库表中。
水平拆分:把一个大表的压力按照相同的表结构分到不同的数据库上或者同一个数据库中的拆分成多个表,每次存储根据分区建做hash取模运算判断出存在哪个字表上面。
事务机制
数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全地不执行。
- 事务必须具备ACID四个特性
原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。
一致性(Consistency)
一致性是指事务必须使数据库从一个一致的状态变到另外一个一致的状态,也就是执行事务之前和之后的状态都必须处于一致的状态。
隔离性(Isolation)
隔离性是指当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离.
持久性(Durability)
持久性是指一个事务一旦被提交了,那么对于数据库中的数据改变就是永久性的,即便是在数据库系统遭遇到故障的情况下也不会丢失提交事务的操作。
- 并发访问数据会出现三种情况:脏读、不可重复读、幻读。
脏读(Dirty Read)
当事务A在修改(insert、delete、update)记录但还未提交时,另一个事务B读取了该记录,此时事务B读到的数据就是脏数据,如果此时事务A回滚了事务,则事务B读到的数据无效。
不可重复读(Non-repeatable Read)
当事务A在读取记录时,另一个事务B修改(delete、update)了该记录并提交,此时事务A再一次读取该记录会读取到被事务B修改后的数据。在一个事务中前后两次读取的数据不一样,因此被称作不可重复读。
幻读(Phantom Read)
当事务A在读取记录时,另一个事务B插入(insert)了新记录并提交,导致事务A再次查询记录时多出了原本不存在的记录,就像看到了幻觉一样,所以被称作幻读。
- 事务的隔离级别
事务的隔离级别描述了事务被隔离的程度,其隔离级别有4个,由低到高依次为Read Uncommitted 、Read Committed 、Repeatable Read 、Serializable。通过设置不同的事务隔离级别可以解决脏读、不可重复读和幻读。
读未提交(Read Uncommitted)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。在实际中很少使用这种隔离级别,其性能并没有比其他隔离级别好多少,且会发生脏读、不可重复读和幻读。
读提交(Read Committed)
在该隔离级别,所有事务都只能看到其他已经提交的事务的执行结果。这是大多数数据库系统的默认隔离级别(MySQL默认的是可重复读),在该隔离级别会发生不可重复读和幻读。
可重复读(Repeatable Read)
这是MySQL默认的事务隔离级别,该隔离级别虽然解决了脏读和不可重复读,但还是无法避免幻读。
可串行化(Serializable)
最高级别的事务隔离级别,通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。但是系统开销花费最高,性能很低,一般很少使用。
- MYSQL 事务处理主要有两种方法:
MySQL数据库默认的存储引擎类型是MyISAM,这种存储引擎类型不支持事务处理。
在MySQL中,只有InnoDB存储引擎类型的数据表才能支持事务处理。
1)用 BEGIN, ROLLBACK, COMMIT来实现
BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认
2)直接用 SET 来改变 MySQL 的自动提交模式:
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
spring事务应用
- 编程式事务处理:所谓编程式事务指的是通过编码方式实现事务,允许用户在代码中精确定义事务的边界。即类似于JDBC编程实现事务管理。管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
- 声明式事务处理:管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
索引原理
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
主流的RDBMS都是把平衡树当做数据表默认的索引数据结构的。
架构能力
用过哪些中间件
tomcat等服务器中间件
redis等缓存中间件
mybatis等数据库中间件
activemq等消息中间件
zookeeper作用
ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现。
分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协
调/通知、集群管理、Master 选举、配置维护,名字服务、分布式同步、分布式锁和分布式队列
等功能。
可以用来做注册中心和配置中心。
分布式锁
- 基于数据库实现分布式锁
基于数据库表:通过表的增删改查实现加解锁
基于数据库排他锁:通过for update来实现加解锁
- 基于缓存实现分布式锁
相比较于基于数据库实现分布式锁的方案来说,基于缓存来实现在性能方面会表现的更好一点。而且很多缓存是可以集群部署的,可以解决单点问题。
目前有很多成熟的缓存产品,包括Redis,memcached.
基于Redis实现分布式锁在网上有很多相关文章,其中主要的实现方式是使用Jedis.setNX方法来实现。
redis的作者Salvatore Sanfilippo,提出了Redlock算法,该算法实现了比单一节点更安全、可靠的分布式锁管理(DLM)。
- 基于Zookeeper实现分布式锁
基于zookeeper临时有序节点可以实现的分布式锁。
大致思想即为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题。
- 三种方案的比较
从理解的难易程度角度(从低到高)
数据库 > 缓存 > Zookeeper
从实现的复杂性角度(从低到高)
Zookeeper > 缓存 > 数据库
从性能角度(从高到低)
缓存 > Zookeeper >= 数据库
从可靠性角度(从高到低)
Zookeeper > 缓存 > 数据库
分布式事务
什么是分布式事务?简单的说,就是一次大操作由不同小操作组成,这些小操作分布在不同服务器上,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
基于XA协议的两阶段提交:MySQL 5.0或者更新版本开始支持XA事务,只有InnoDB引擎支持XA协议。详细阅读
TCC编程模式: LCN
消息最终一致性:RocketMQ
缓存
本地缓存:ehcache等
缓存中间件:redis,memcached
CAP和BASE和ACID的理解
- ACID模型
ACID是传统数据库常用的设计理念,追求强一致性模型。
关系数据库的ACID模型拥有 高一致性 + 可用性 很难进行分区:
Atomicity原子性:一个事务中所有操作都必须全部完成,要么全部不完成。
Consistency一致性. 在事务开始或结束时,数据库应该在一致状态。
Isolation隔离层. 事务将假定只有它自己在操作数据库,彼此不知晓。
Durability. 一旦事务完成,就不能返回。
ACID模型要求一个事物必须满足上面的四点,这是对关系型传统数据库的指导性依据。而非关系型数据库NoSql则不再依赖这一模型。
- CAP理论
CAP理论正式成为分布式计算领域的公认定理。
CAP理论为:
一个分布式系统最多只能同时满足:
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容错性) 可靠性
这三项中的两项。
- BASE理论
BASE:Basically,Available,Soft state,Eventually consistent四个词组的首字母,它的意思是:基本可用+软状态+最终一致性
eBay的架构师Dan Pritchett源于对大规模分布式系统的实践总结,在ACM上发表文章提出BASE理论,BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性(Strong Consistency,CAP的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性(Eventual Consitency)。
BASE是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。
基本可用(Basically Available)
基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。
电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。
软状态( Soft State)
软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。
最终一致性( Eventual Consistency)
最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。
BASE模型是传统ACID模型的反面,不同与ACID,BASE强调牺牲高一致性,从而获得可用性,数据允许在一段时间内的不一致,只要保证最终一致就可以了。
BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性: Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库) Soft state软状态 状态可以有一段时间不同步,异步。 Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时一致。
BASE思想的主要实现有
1.按功能划分数据库
2.sharding碎片
沟通和学习能力职业规划
- 1.平时怎么学习
- 2.喜欢逛什么社区
- 3.未来打算如何
技术要求
- 1.多线程模型 - > 各种状态之间转换 -> jdk常见的并发类 -> 如何保证线程安全 -> volatile实现原理 -> 线程池与队列 -> 调优
volatile实现原理:
- 2.spring 特点 -> AOP原理 -> 代理种类 -> 实现细节 -> CGLib局限 -> 性能如何
- 3.JVM组成 -> 内存模型 -> 垃圾收集算法 -> 类加载 -> 收集器类型 -> 如何调优
- 4.spring MVC 组成 - > 怎么映射控制器 -> 控制器单例否 -> 拦截器应用
- 5.使用过MySQL -> 数据库引擎区别 -> 事务控制 - > 隔离级别 -> 加锁种类区别 -> spring事务传播 -> 区别
- 6.分布式和集群区别 -> 服务发现和负载均衡 -> 中间件 -> 分布式事务处理 -> 缓存设计