泛型擦除和参数类型
泛型好处编译器类型检查
用在父类,给子类继承
泛型擦除在编译器把泛型变为泛型的父类,如没有指定父类则是Object
获取参数类型发送X5请求用到
1234567891011public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>() {}; Type type = map.getClass().getGenericSuperclass(); if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; Type[] typeArgs = paramType.getActualTypeArguments(); for (Type arg : typeArgs) { Syste ...
事务三大问题的解决方案
什么是事务?事务是很多个SQL操作的总和,一个事务内部的操作要么一起成功、要么一起失败。
事务的四大隔离级别和三大问题四大隔离级别
读未提交:事务A未提交事务,在事务A中能看到 事务B 未提交事务时修改的数据
读提交:事务A未提交事务,在事务A中能看到 事务B 提交事务后发生变动的数据,可能在事务A中不希望能看到在操作时数据被修改
可重复读:指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的
串行化:事务A未提交之前,事务B不允许修改数据,事务B会被阻塞,直到事务A提交事务
三大问题由于MySQL支持多个客户端同时连接,在并发事务的时候就会出现问题
脏读:读到了其他未提交的事务修改的结果
不可重复读:同一条select语句前后的结果数据不一致
幻读:同一条select语句前后的结果条数不一致
脏读
不可重复读
幻读
读未提交
√
√
√
读已提交
×
√
√
可重复读
×
×
√
串行化
×
×
×
三大问题的解决方案脏读其实一般来说,用到的隔离级别至少是读已提交RC,或者是可重复读RR,基本是没有脏读的问题的
不可重复读前面也提 ...
IoC
什么是IoC?IoC是控制反转,控制的是bean的创建、管理、生命周期,反转的是控制的权力,对于Spring来说,就是将bean的控制权交给Spring框架管理。
另一种说法是把IoC当作一个bean的容器,叫做IoC容器,我们可以从容器中获取bean。
控制反转的优点:
方便:无需关注bean的具体实现过程,相当于一个黑盒
什么是DI?DI是依赖注入,DI是IoC的一种具体实现,表现为将设置对象的依赖的控制权反转,意思就是通过DI实现bean生命周期控制权的反转。同理不自己new对象,而是Spring项目启动的时候,IoC容器帮你new对象。
依赖是程序运行时对象需要的外部的一些数据资源,注入是把这些数据资源填充到bean对象的内部,让对象间产生依赖关系。
DI优点:
解耦:它把对象之间的依赖关系转成用配置文件来统一管理,避免不同业务互相影响,利于修改。
一般有三种方式注入:
构造器注入12345678910111213@Configurationpublic class AppConfig { @Bean public Item item1() ...
Spring事务
l
什么是Spring事务?Spring 事务是在数据库事务的基础上进行封装扩展:
支持原有的数据库事务的隔离级别,加入了事务传播的概念
提供多个事务的合并或隔离的功能
提供声明式事务(@Transactional),让业务代码与事务分离,减少代码侵入,事务变得更易用 (AOP)
总的来说就是能够更加简便的管理事务,不管是不同方法公用同一个事务或者是不同方法有自己的事务
Spring事务应用Spring事务管理类型编程式事务通过 TransactionTemplate或者TransactionManager手动管理事务,实际应用中很少使用
声明式事务标注@Transactional注解
Spring事务属性TransactionDefinition隔离级别(Isolation Level)和数据库的隔离级别基本一样
DEFAULT:使用数据库默认的隔离级别。
READ_UNCOMMITTED:允许读取未提交的数据。
READ_COMMITTED:只允许读取已提交的数据。
REPEATABLE_READ:确保多次读取的结果是一致的。
SERIALIZABLE:提供严格的事务隔离,以 ...
Spring源码详解
什么是Spring?Spring是一个框架,封装了许多代码可以简化我们的开发,有两个核心,如果搞懂了就相当于把Spring框架给搞明白了,一个是IoC、另一个是AOP。
IoC什么是IoC?IoC(Inversion of Control),即控制反转,这是一种设计思想,在Spring指将对象的控制权交给Spring容器,由容器来实现对象的创建、管理,程序员只需要从容器获取想要的对象就可以了。这里引申一个词叫DI(Dependency Injection),即依赖注入,他是IoC的一种具体实现方式,类似于Map和HashMap的关系,指对象创建时的属性赋值交给Spring容器来做。
还有一种理解是把IoC理解为Spring容器,底层是一个Map,key是beanName,value是bean。
为什么需要IoC?
不用手动new对象,将对象创建和业务解耦
无需关注对象创建的过程,只管使用就行
IoC怎么使用?声明beanxml文件
@Component及其衍生注解
@Configuration和@Bean
获取beanbeanFactory.getBean(String beanNa ...
Runnable、Callable、FutureTask、CompletableFuture
Runnable和Callable都是代表一个任务,可以把这个任务交给线程或者线程池执行
都是函数式接口,可以用lambda表达式替代
Runnable没有返回值,任务内不抛出异常
Callable有返回值,任务内可以抛出异常,Callable需要用FutureTask包装才能交给线程执行
12345@FunctionalInterfacepublic interface Runnable { public abstract void run();}
12345@FunctionalInterfacepublic interface Callable<V> { V call() throws Exception;}
Callable和FutureTaskFutureTask实现了Runnable接口,Callable需要用FutureTask包装就可以交给线程执行
同时FutureTask是实现了Future接口,有get()方法等待异步任务结果,用了类似于Condiction条件队列的虚拟链表 ...
IO
File类File是文件或者文件夹的抽象,File代表的仅仅是一个路径而已
新建
createNewFile():创建文件
mkdir():创建目录,如果新目录的前面的路径不存在,则不创建
mkdirs():创建多级目录,不管新目录的前面的路径不存在,都会创建
判断
isDirectory():是否是目录
isFile:是否是文件
exitsts():是否存在
getAbsolutePath():获取绝对路径
getPath():获取相对路径
getName():获取名字
list():列出所有的文件或者目录的名字
listFiles():列出所有的文件或者目录的路径
流用记事本打开能看懂就用字符流,看不懂就用字节流
字节流
字节输出流OutputStreamFileOutputStreamFileOutputStream默认是覆盖写入,需要使用其它构造器来实现追加写入
String.getBytes():获取一个字节数组
write(int num):写一个字节
write(byte[] bytes):写一个字节数组
write(byte[] bytes, int off, i ...
BIO、NIO、AIO
BIO、NIO、AIO对比不管是哪种IO,都是使用socket进行的不同主机间的通信,利用输入输出流进行消息的发送和接收
BIO(同步阻塞IO):一个请求对应一个服务端线程
NIO(同步非阻塞IO):IO多路复用模式,一个选择器管理多个请求
AIO(异步非阻塞IO):
BIOBIO就是服务端需要阻塞等待客户端的数据发送。
当连接数越来越多,服务端的资源会被占用(文件、CPU、内存)等
线程间竞争和上下文切换的消耗
由于线程的资源占用,导致最大并发量较低
简单了解SpringMVC源码
SpringMVC启动流程主要就是在tomcat启动期间,根据WebApplicationInitializer会创建两个容器,一个是父容器(原本的Spring容器),一个是子容器(SpringMVC容器,可以获取到Spring容器的bean);
tomcat启动完成之后进行初始化,利用钩子的回调机制初始化Spring容器(调用refresh()),然后根据DispatcherServlet的init()初始化SpringMVC容器。
如何处理请求?通过DispatcherServlet管理请求,主要研究doDispatch()方法
简单了解并发容器
阻塞队列阻塞队列用到了类似于生产者-消费者模式,和普通队列不同,在队列为空的时候消费动作会被阻塞,在队列满的时候生产动作会被阻塞。
ArrayBlockingQueue成员变量1234567891011121314151617181920212223// 底层存储元素的数组final Object[] items;// 在索引处取出元素int takeIndex;// 在索引处放入元素int putIndex;// 当前数组内的元素个数int count;// 用ReentrantLock实现并发安全final ReentrantLock lock;// 用Condition notEmpty实现消费者阻塞等待private final Condition notEmpty;// 用Condition notFull实现生产者阻塞等待private final Condition notFull;// 迭代器transient Itrs itrs = null;
put()1234567891011121314151617public void put(E e) throws I ...