Java基础
1. @Transactional的失效问题
在同一个类中,方法A(没有加@Transactional注解)调用方法B(加了@Transactional注解),则事务失效,原因是通过**this.**调用,不经过 AOP,导致事务不开启。
事务传播特性有哪几种?
目前,Spring在TransactionDefinition类中定义了以下7种传播特性,具体特性我们接下来会分析:
PROPAGATION_REQUIRED:如果不存在外层事务,就主动创建事务;否则使用外层事务
PROPAGATION_SUPPORTS:如果不存在外层事务,就不开启事务;否则使用外层事务
PROPAGATION_MANDATORY:如果不存在外层事务,就抛出异常;否则使用外层事务
PROPAGATION_REQUIRES_NEW:总是主动开启事务;如果存在外层事务,就将外层事务挂起
PROPAGATION_NOT_SUPPORTED:总是不开启事务;如果存在外层事务,就将外层事务挂起
PROPAGATION_NEVER:总是不开启事务;如果存在外层事务,则抛出异常
PROPAGATION_NESTED:如果不存在外层事务,就主动创建事务;否则创建嵌套的子事务
注意:默认情况下当发生RuntimeException的情况下,事务才会回滚,所以要注意一下,如果你在程序发生错误的情况下,有自己的异常处理机制定义自己的Exception,必须从RuntimeException类继承,这样事务才会回滚!
2. MyBatis的sql语句中,使用#做模糊查询该如何写
如果没有特殊要求:
直接写 where name like #{?} => where name like ‘%?%’
否则,使用concat函数:
where name like concat(’%’,#{?},’%’) => where name like ‘%?% ’
where name like concat(#{?},’%’) => where name like ‘?%’
where name like concat(’%’,#{?}) => where name like ‘%?’
3. 内部类怎么写
特点
- 内部类可以直接访问外部类中的成员,包括私有成员
- 外部类要访问内部类的成员,必须要建立内部类的对象
- 在成员位置的内部类是成员内部类
- 在局部位置的内部类是局部内部类
成员内部类
public class Test01 {
public static void main(String[] args) {
}
class TestSon{
public TestSon() {
}
}
}
局部内部类
public class Test01 {
public static void main(String[] args) {
class TestSon{
public TestSon() {
}
}
}
}
匿名内部类
public class Test01 {
public static void main(String[] args) {
new Runnable() {
@Override
public void run() {
}
};
}
}
4. 类加载顺序
public class Test01 {
{
System.out.println("父类构造代码块");
}
static {
System.out.println("父类静态代码块");
}
public Test01() {
System.out.println("父类构造方法");
}
}
class Test02 extends Test01{
{
System.out.println("子类构造代码块");
}
static {
System.out.println("子类静态代码块");
}
public Test02() {
System.out.println("子类构造方法");
}
public static void main(String[] args) {
Test02 test02 = new Test02();
}
}
父类静态代码块
子类静态代码块
父类构造代码块
父类构造方法
子类构造代码块
子类构造方法
5. JVM内存结构
这里介绍的是JDK1.8 JVM内存模型。1.8同1.7比,最大的差别就是:元数据区取代了永久代。元空间的本质和永久代类似,都是对JVM规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存。
6. 字符串的操作用什么API
StringBuffer是线程安全,可以不需要额外的同步用于多线程中;
StringBuilder是非同步,运行于多线程中就需要使用着单独同步处理,但是速度就比StringBuffer快多了;
StringBuffer与StringBuilder两者共同之处:可以通过append、indert进行字符串的操作。
7. 创建线程的几种方式
-
继承Thread类
-
实现Runnable接口
-
使用Executor框架来创建线程池
-
通过Callable接口和Future创建线程
(1)创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
(2)创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。
(3)使用FutureTask对象作为Thread对象的target创建并启动新线程。
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
8. 创建线程池的几种方式
- newFixedThreadPool
创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。 - newSingleThreadExecutor
创建一个单线程的线程池,可保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 - newCachedThreadPool
创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。 - newScheduledThreadPool
创建一个周期性的线程池,支持定时及周期性执行任务。
注意:
FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
9. nacos的特性
- 服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。 Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
- 服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认 5s发送一次心跳。
- 服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。
- 服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清 单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存
- 服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况,对于超过15s没有收到客户端心跳的实例会将它的 healthy属性置为false(客户端服务发现时不会发现),如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送 心跳则会重新注册)
10. mysql优化
- 合理的数据库设计
设计表结构时,遵循三范式
第一范式:原子性,数据表中的每个字段都是不可拆分的最小单元
第二范式:满足第一范式后,表中的每一列必须有唯一性,都必须依赖于主键
第三范式:满足第二范式后,表中的每一列只与主键直接相关而不是间接相关,字段没有冗余 - sql优化
优化insert语句,批量插入比单列插入效率高
尽量避免子查询,用join多表连接查询代替
where条件字段上需要建立索引,但where条件上不要使用函数运算,以免索引失效
多表连接的字段上需要建立索引,这样可以极大的提高表连接的效率
优化group by,不要使用select * - 索引优化
对查询频率高的字段设置索引,
对唯一性差的列不需要建立索引
对修改频繁的列不建立索引
索引并非越多越好,最好不超过六个,索引也是一张张表,占内存
使用短索引,提高索引访问时的I/O效率,因此也提升了mysql的查询效率 - 索引失效
没有遵循最左前缀
索引列中包含null,引擎将放弃索引
模糊查询以%开头
where后边的or两边如果有一边没有建立索引,索引会失效
where后边的字段参与了函数运算
使用is null , is not null, !, <> 会导致索引失效
11. RestController和Controller的区别
@RestController注解相当于@ResponseBody和@Controller的结合
但是在使用@RestController注解的时候需要注意几个问题:
1.如果使用@RestController注解Controller,那么该Controller中的方法就无法返回jsp页面,就是说如果在方法中return “xx”,那么它只会返回"xx"的内容,因为@RestController中相当于已经有了@RessponseBody的注解效果,所以它无法返回jsp,html界面,配置的InternalResourceViewResolver不工作,只返回return的内容。
2.根据第一条的规定,如果该Controller中需要返回jsp,html界面,那么就需要使用@Controller注解Controller,不能用@RestController。
3.第一条中说到@RestController注解的Controller只返回return中的内容,所以如果我们在Controller方法中需要返回JSON、XML或者我们自己定义的类型到页面中,那么就需要使用@ResponseBody注解该方法。