java面试题总结
1基础
1. 什么是Java虚拟机?
-Java虚拟机(JVM)是Java平台的核心组件,负责将Java源代码编译成字节码后,在操作系统上运行。Java虚拟机在运行时提供内存管理、垃圾回收以及安全机制等功能。
2. Java的数据类型有哪些? Java的数据类型分为基本数据类型和引用数据类型。基本数据类型包括byte、short、int、long、float、double、char、boolean,引用数据类型包括类、接口、数组等。
3. final, finally, finalize 的区别?
final是关键字,修饰变量、方法、类等,表示不可改变的;finally是关键字,用于try-catch语句中,表示无论异常是否发生,finally语句块中的代码都会被执行;finalize是Object类中的方法,用于垃圾回收,表明该对象在垃圾回收前需要执行的操作。
4. 面向对象的特征有哪些?
面向对象的特征包括
封装、继承、多态三个方面。封装是指隐藏数据和方法,只提供接口给外部访问;继承是指子类继承父类的属性和方法;多态是指同样的方法名可以有不同的实现。
5. 抽象类和接口有哪些区别?
-抽象类是类,可以有构造器,不能被实例化,可以有抽象方法,抽象方法必须在子类中被实现或者子类也是抽象类;接口是一种特殊的抽象类,只能包含常量和抽象方法,实现接口的类必须实现接口中的所有方法。
6. 说说Java中的三种引用类型? Java中的引用类型包括强引用、软引用和弱引用。强引用指被引用对象不会被垃圾回收,直到没有任何强引用指向该对象;软引用指被引用对象在内存不足时才会被垃圾回收;弱引用指被引用对象不会被强引用指向时就会被垃圾回收。
7. 什么是Java中的反射?
- 反射是Java语言的一种特性,可以在运行时动态地获取类的信息,包括类的属性、方法、构造器等,并可以在运行时调用这些方法。反射的主要实现类为Class类,可以使用getClass()方法获取一个对象的类型。
8. 什么是Java中的泛型?
- 泛型是指将类、接口和方法的参数类型抽象化,使得代码可以更加通用化,提高代码的复用性和安全性。通过使用泛型,可以实现代码的类型检查和类型转换,避免因类型转换引起的运行时异常。
9. 简要说明Java中的多线程编程?
- Java中的多线程编程可以通过继承Thread类或实现Runnable接口来创建线程。可以使用synchronized关键字来实现线程同步,避免数据竞争。Java中还提供了Lock、Semaphore、CountDownLatch等工具类来实现更加复杂的线程同步。
10. 说说Java中的异常处理机制?
- Java中的异常处理机制通过try-catch块来捕获和处理异常。当程序出现异常时,可以通过throw关键字将异常对象抛出。异常处理机制中还包括finally语句块和多个catch语句块,用于处理不同类型的异常和释放资源等操作。
11. 什么是ORM?常见的ORM框架有哪些?
- ORM(Object-Relational Mapping)是指通过将关系型数据库与面向对象编程相结合,将关系型数据转化成对象的形式进行操作。常见的ORM框架有Hibernate、MyBatis等。
12. 什么是Java中的IO编程?
- Java中的IO编程是指对文件、目录、网络等进行输入输出操作。Java中的IO操作包括字节流和字符流两种,字节流用于处理二进制数据,字符流用于处理文本数据。常见的IO类包括InputStream、OutputStream、Reader、Writer等。
13. 什么是Java中的网络编程?
- Java中的网络编程是指使用网络协议在计算机之间进行通信。Java中通过Socket套接字来实现网络编程,常用的网络协议包括TCP和UDP。
14. Servlet和JSP的区别是什么?
- Servlet是运行在服务器端的Java程序,用于处理HTTP请求和响应;JSP是JavaServer Pages的缩写,是一种动态网页技术,可以将Java代码嵌入HTML中。Servlet和JSP都可以用于实现Web应用。
15. 什么是Java中的集合框架?常用的集合类有哪些?
- Java中的集合框架是指一组用于存储数据的类和接口。Java中的集合框架包括List、Set、Map等接口和实现类,常用的集合类有ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等。
Java中常用的集合类:
1. ArrayList:动态数组,支持随机访问,插入和删除操作效率较低。
2. LinkedList:双向链表,支持在头部和尾部进行插入和删除操作,但随机访问效率低。
3. HashSet:基于HashMap的Set实现,不支持重复元素。
4. TreeSet:基于TreeMap的Set实现,元素有序,支持自定义排序。
5. HashMap:哈希表,键值对存储,不保证元素有序。
6. TreeMap:红黑树,键值对存储,元素按照键值有序。
7. ConcurrentHashMap:线程安全的哈希表,支持高并发访问。
8. ArrayDeque:双端队列,支持在头部和尾部进行插入和删除操作。
9. PriorityQueue:优先队列,通过堆实现,保证队列头元素最小或最大。
这些集合类都实现了Java中的Collection接口或Map接口,可以通过调用它们提供的方法来对集合元素进行操作。
16. 什么是Java中的注解?常见的注解有哪些?
- Java中的注解是一种元数据,可以在代码中标记类、方法、变量等元素的特殊信息。常见的注解有@Override、@Deprecated、@SuppressWarnings、@FunctionalInterface等。
17. 说说Java中的加密和解密方式?
- Java中的加密和解密方式包括对称加密和非对称加密两种。对称加密包括DES、AES、DESede等算法,加密和解密使用相同的密钥,适用于加解密数据量较小的场景;非对称加密包括RSA、DSA等算法,加密和解密使用不同的密钥,适用于加解密数据量较大的场景。
18. 什么是Java中的Lambda表达式?
- Lambda表达式是Java 8引入的一种新的语法,用于简化代码,使得代码更加简洁易读。Lambda表达式可以用于函数式接口的实现,可以传递代码块作为参数,使得代码更加灵活。
19. 什么是Java中的Stream API?
- Stream API是Java 8引入的一个新特性,用于对Java中的集合进行函数式操作。可以用于过滤、映射、排序、归约等操作,使得编写代码更加简单、易于维护和调试。
20. 什么是Java中的函数式编程?
- 函数式编程是指使用函数作为基本的构造块,通过将函数组合的方式来构建软件系统。Java中的函数式编程主要基于Lambda表达式和Stream API实现,能够带来更加简洁、清晰、易于维护和测试的代码。
2数据库
1如何查看sql走了索引没?
可以使用explain命令,查看mysql的执行计划。
例如:
explain select * from `order` where code='002';
2.分类
COUNT:统计行数量
SUM:获取单个列的合计值
AVG:计算某个列的平均值
MAX:计算列的最大值
MIN:计算列的最小值
3.SQL关键字(必会)
1.分页
MySQL的分页关键词limit
SELECT * FROM student3 LIMIT 2,6; 查询学生表中数据,从第三条开始显示,显示6条
2.分组
MySQL的分组关键字:group by
SELECT sex, count(*) FROM student3 GROUP BY sex;
3.去重
去重关键字:distinct
select DISTINCT NAME FROM student3;
4.SQL Select 语句完整的执行顺序: (必会)
查询中用到的关键词主要包含如下展示,并且他们的顺序依次为
(1) form 表 从哪个表查
(2) Left/right join on 关联表
(3) where 过滤条件
(4) group by 分组
(5) avg()/sum()等 聚合
(6) Having 继续过滤
(7) select 查询
(8) order by asc/desc 排序
(9) Limit 分页
205.数据库三范式(必会)
第一范式:1NF 原子性,列或者字段不能再分,要求属性具有原子性,不可再分解;
第二范式:2NF 唯一性,一张表只说一件事,是对记录的惟一性约束,要求记录有惟一标识,
第三范式:3NF 直接性,数据不能存在传递关系,即每个属性都跟主键有直接关系,而不是间接关系。
6.存储引擎 (高薪常问)
1.MyISAM存储引擎
主要特点:
MySQL5.5版本之前的默认存储引擎
支持表级锁(表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁);
不支持事务,外键。
适用场景:对事务的完整性没有要求,或以select、insert为主的应用基本都可以选用MYISAM。在Web、数据仓库中应用广泛。
特点:
1、不支持事务、外键
2、每个myisam在磁盘上存储为3个文件,文件名和表名相同,扩展名分别是
.frm -------存储表定义
.MYD --------MYData,存储数据
.MYI --------MYIndex,存储索引
2.InnoDB存储引擎
主要特点:
MySQL5.5版本之后的默认存储引擎;
支持事务;
支持行级锁(行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁);
支持聚集索引方式存储数据。
7.数据库事务(必会)
1.事务特性
原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。
一致性:事务的执行使得数据库从一种正确状态转换成另一种正确状态
隔离性:在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务,
持久性:事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。
2.隔离级别
(1)读未提交(read Uncommited):
在该隔离级别,所有的事务都可以读取到别的事务中未提交的数据,会产生脏读问题,在项目中基本不怎么用, 安全性太差;
(2) 读已提交(read commited):
这是大多数数据库默认的隔离级别,但是不是MySQL的默认隔离级别;这个隔离级别满足了简单的隔离要求:一个事务只能看见已经提交事务所做的改变,所以会避免脏读问题;
由于一个事务可以看到别的事务已经提交的数据,于是随之而来产生了不可重复读和虚读等问题(下面详细介绍这种问题,结合问题来理解隔离级别的含义);
(3 ) 可重复读(Repeatable read):
这是MySQL的默认隔离级别,它确保了一个事务中多个实例在并发读取数据的时候会读取到一样的数据;不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
(4) 可串行化(serializable):
事物的最高级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争,一般为了提升程序的吞吐量不会采用这个;
8.索引
索引的概念和优点(了解)
概念:
索引存储在内存中,为服务器存储引擎为了快速找到记录的一种数据结构。索引的主要作用是加快数据查找速度,提高数据库的性能。
优点:
(1) 创建唯一性索引,保证数据库表中每一行数据的唯一性
(2) 大大加快数据的检索速度,这也是创建索引的最主要的原因
(3) 加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
(4) 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
索引的分类(必会)
(1) 普通索引:最基本的索引,它没有任何限制。
(2) 唯一索引:与普通索引类似,不同的就是索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
(3) 主键索引:它是一种特殊的唯一索引,用于唯一标识数据表中的某一条记录,不允许有空值,一般用 primary key 来约束。
(4) 联合索引(又叫复合索引):多个字段上建立的索引,能够加速复合查询条件的检索。
(5) 全文索引:老版本 MySQL 自带的全文索引只能用于数据库引擎为 MyISAM 的数据表,新版本 MySQL 5.6 的 InnoDB 支持全文索引。默认 MySQL 不支持中文全文检索,可以通过扩展 MySQL,添加中文全文检索或为中文内容表提供一个对应的英文索引表的方式来支持中文。
索引的底层实现原理(高薪常问)
1.索引结构
索引是在Mysql的存储引擎(InnoDB,MyISAM)层中实现的, 而不是在服务层实现的. 所以每种存储引擎的索引都不一定完全相同, 也不是所有的存储引擎都支持所有的索引类型的, Mysql目前提供了以下4种索引:
B+Tree 索引: 最常见的索引类型, 大部分索引都支持B+树索引.
Hash 索引: 只有Memory引擎支持, 使用场景简单.
R-Tree索引(空间索引): 空间索引是MyISAM引擎的一个特殊索引类型, 主要地理空间数据, 使用也很少.
S-Full-text(全文索引): 全文索引也是MyISAM的一个特殊索引类型, 主要用于全文索引, InnoDB从Mysql5.6版本开始支持全文索引.
2. BTree结构
B+Tree是在BTree基础上进行演变的, 所以我们先来看看BTree, BTree又叫多路平衡搜索树, 一颗m叉BTree特性如下:
(1) 树中每个节点最多包含m个孩子.
(2) 除根节点与叶子节点外, 每个节点至少有[ceil(m/2)] 个孩子(ceil函数指向上取整).
(3) 若根节点不是叶子节点, 则至少有两个孩子.
(4) 每个非叶子节点由n个Key和n+1个指针组成, 其中 [ceil(m/2) -1 ] <= n <= m-1.
以5叉BTree为例, key的数量: 公式推导 [ceil(m/2) -1 ] <= n <= m-1.
所以 2 <= n <= 4, 中间节点分裂父节点,两边节点分裂.
3.B+Tree 结构
B+Tree为BTree的变种, B+Tree与BTree的区别:
1.B+Tree的叶子节点保存所有的key信息, 依key大小顺序排列.
2.B+Tree叶子节点元素维护了一个单项链表.
所有的非叶子节点都可以看作是key的索引部分.
由于B+Tree只有叶子节点保存key信息, 查询任何key都要从root走的叶子. 所以B+Tree查询效率更稳定.
Mysql中的B+Tree
MySql索引数据结构对经典的B+Tree进行了优化, 在原B+Tree的基础上, 增加了一个指向相邻叶子节点的链表指针, 就形成了带有顺序指针的B+Tree, 提高区间访问的性能.
MySql中的B+Tree索引结构示意图:
4. 如何避免索引失效(高薪常问)
(1) 范围查询, 右边的列不能使用索引, 否则右边的索引也会失效.
索引生效案例
select * from tb_seller where name = “小米科技” and status = “1” and address = “北京市”;
select * from tb_seller where name = “小米科技” and status >= “1” and address = “北京市”;
索引失效案例
select * from tb_seller where name = “小米科技” and status > “1” and address = “北京市”;
address索引失效, 因为status是大于号, 范围查询.
(2) 不要在索引上使用运算, 否则索引也会失效.
比如在索引上使用切割函数, 就会使索引失效.
select * from tb_seller where substring(name, 3, 2) = “科技”;
(3) 字符串不加引号, 造成索引失效.
如果索引列是字符串类型的整数, 条件查询的时候不加引号会造成索引失效. Mysql内置的优化会有隐式转换.
索引失效案例
select * from tb_seller where name = “小米科技” and status = 1
(4) 尽量使用覆盖索引, 避免select *, 这样能提高查询效率.
如果索引列完全包含查询列, 那么查询的时候把要查的列写出来, 不使用select *
select sellerid, name, status from tb_seller where name = “小米科技” and staus = “1” and address = “西安市”;
(5) or关键字连接
用or分割开的条件, 如果or前面的列有索引, or后面的列没有索引, 那么查询的时候前后索引都会失效
如果一定要用or查询, 可以考虑下or连接的条件列都加索引, 这样就不会失效了.
• 索引失效案例:
9.数据库锁(高薪常问)
1.行锁和表锁
1.主要是针对锁粒度划分的,一般分为:行锁、表锁、库锁
行锁:访问数据库的时候,锁定整个行数据,防止并发错误。
表锁:访问数据库的时候,锁定整个表数据,防止并发错误。
2.行锁 和 表锁 的区别:
表锁: 开销小,加锁快,不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低
行锁: 开销大,加锁慢,会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高
2.悲观锁和乐观锁
(1)悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。
传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
(2)乐观锁: 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。
乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
10.MySql优化(高薪常问)
定位执行效率慢的sql语句.(了解)
命令:show status like ‘Com____’,通过这条命令, 我们可以知道当前数据库是以查询为主还是更新为主. 如果是查询为主, 就重点查询; 如果增删改多就重点优化写入操作.
explain + sql语句查询sql执行过程, 通过执行计划,我们能得到哪些信息:
A:哪些步骤花费的成本比较高
B:哪些步骤产生的数据量多,数据量的多少用线条的粗细表示,很直观
C:这条sql语句是否走索引
show profile分析SQL,可以查看所有sql语句的执行效率(所用时间). 前提是这个命令需要被打开, 严格的说也就是打开这个命令后执行的所有sql语句, 它都能记录下执行时间, 并展示出来. 可以通过这个命令分析哪些sql语句执行效率低. 耗时长, 就更有针对性的优化这条sql.
慢查询日志(常用的工具)
慢查询日志记录了所有执行时间超过参数 long_query_time的sql语句的日志, long_query_time默认为10秒(可以通过配置文件设置), 日志保存在 /var/lib/mysql/目录下, 有个slow_query.log文件,
2) 优化索引(高薪)
2.1 索引设计原则
索引的设计需要遵循一些已有的原则, 这样便于提升索引的使用效率, 更高效的使用索引.
对查询频次较高, 且数据量比较大的表, 建立索引.
索引字段的选择, 最佳候选列应当从where子句的条件中提取, 如果where子句中的组合比较多, 那么应当挑选最常用, 过滤效果最好的列的组合.
使用唯一索引, 区分度越高, 使用索引的效率越高.
索引并非越多越好, 如果该表赠,删,改操作较多, 慎重选择建立索引, 过多索引会降低表维护效率.
使用短索引, 提高索引访问时的I/O效率, 因此也相应提升了Mysql查询效率.
如果where后有多个条件经常被用到, 建议建立符合 索引, 复合索引需要遵循最左前缀法则, N个列组合而成的复合索引, 相当于创建了N个索引.
复合索引命名规则 index_表名_列名1_列名2_列明3
比如:create index idx_seller_name_sta_addr on tb_seller(name, status, address)
2.2 避免索引失效
如果在查询的时候, 使用了复合索引, 要遵循最左前缀法则, 也就是查询从索引的最左列开始, 并且不能跳过索引中的列.
尽量不要在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。
不做列运算where age + 1 = 10,任何对列的操作都将导致表扫描,它包括数据库教程函数.计算表达式等, 都会是索引失效.
查询 like,如果是 ‘%aaa’ 也会造成索引失效.
应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
Sql语句调优(高薪)
根据业务场景建立复合索引只查询业务需要的字段,如果这些字段被索引覆盖,将极大的提高查询效率.
多表连接的字段上需要建立索引,这样可以极大提高表连接的效率.
where条件字段上需要建立索引, 但Where条件上不要使用运算函数,以免索引失效.
排序字段上, 因为排序效率低, 添加索引能提高查询效率.
优化insert语句: 批量列插入数据要比单个列插入数据效率高.
优化order by语句: 在使用order by语句时, 不要使用select , select 后面要查有索引的列, 如果一条sql语句中对多个列进行排序, 在业务允许情况下, 尽量同时用升序或同时用降序.
优化group by语句: 在我们对某一个字段进行分组的时候, Mysql默认就进行了排序, 但是排序并不是我们业务所需的, 额外的排序会降低效率. 所以在用的时候可以禁止排序, 使用order by null禁用.
select age, count() from emp group by age order by null
尽量避免子查询, 可以将子查询优化为join多表连接查询.
合理的数据库设计(了解)
根据数据库三范式来进行表结构的设计。设计表结构时,就需要考虑如何设计才能更有效的查询, 遵循数据库三范式:
i. 第一范式:数据表中每个字段都必须是不可拆分的最小单元,也就是确保每一列的原子性;
ii. 第二范式:满足一范式后,表中每一列必须有唯一性,都必须依赖于主键;
iii. 第三范式:满足二范式后,表中的每一列只与主键直接相关而不是间接相关(外键也是直接相关),字段没有冗余。
注意:没有最好的设计,只有最合适的设计,所以不要过分注重理论。三范式可以作为一个基本依据,不要生搬硬套。有时候可以根据场景合理地反规范化:
A:保留冗余字段。当两个或多个表在查询中经常需要连接时,可以在其中一个表上增加若干冗余的字段,以 避免表之间的连接过于频繁,一般在冗余列的数据不经常变动的情况下使用。
B:增加派生列。派生列是由表中的其它多个列的计算所得,增加派生列可以减少统计运算,在数据汇总时可以大大缩短运算时间, 前提是这个列经常被用到, 这也就是反第三范式。
C:分割表。
数据表拆分:主要就是垂直拆分和水平拆分。
水平切分:将记录散列到不同的表中,各表的结构完全相同,每次从分表中查询, 提高效率。
垂直切分:将表中大字段单独拆分到另外一张表, 形成一对一的关系。
D: 字段设计
1 表的字段尽可能用NOT NULL
2.字段长度固定的表查询会更快
3.把数据库的大表按时间或一些标志分成小表
3框架
java设计模式
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
1.MVC的工作流程:
用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器
2 Spring MVC的工作原理
(1)用户通过客户端向服务器发送请求,请求被前端控制器DispatcherServlet所拦截;
(2)DispatcherServlet拦截到请求后,会调用HandlerMapping处理器映射器;
(3)处理器映射器根据请求URL找到具体的处理器,生成处理器对象及处理器拦截器(如果有者生成)一并返回给DispatcherServlet;
(4)DispatcherServlet会通过返回信息选择合适的HandlerAdapter(处理器适配器);
(5)HandlerAdapter会调用Handler(处理器),这里的处理器指的就是程序中编写的Controller类,也被称为后端控制器;
(6)Controller执行完成后,会返回一个ModelAndView对象,该对象中会包含视图名或包含模型和视图名;
(7)HandlerAdapter将ModelAndView对象返回给DispatcherServlet;
(8)DispatcherServlet会将ModelAndView对象选择一个合适的VIewResolver(视图解析器);
(9)ViewResolver解析后,会向DispatcherServlet中返回具体的View(视图);
(10)DispatcherServlet对View进行渲染(即将模型数据填充至视图中);
(11)视图渲染结果会返回给返回给客户端浏览器显示。
3 IOC和AOPd描述和区别
IoC(控制反转): 在传统的编程模式中,一个对象通常会负责自己的依赖关系,它自己创建和管理其他对象,这样的方式通常被称为紧耦合。这样的紧耦合往往会导致代码的可维护性和可扩展性下降。为了解决这个问题,IoC被提出来了。
IoC是一种松耦合的设计模式,通过将依赖关系的控制权交给容器,让容器来负责对象的创建、管理、协调以及注入。这样,对象之间的依赖关系将由容器来处理,这种解耦可以使代码更加灵活、可扩展和易于维护。
在Java中,IoC通常通过依赖注入(DI)实现。依赖注入是指在对象创建时,容器将依赖对象注入到目标对象中,从而消除了对象间的直接依赖。依赖注入可以通过构造函数注入、setter方法注入或字段注入等方式实现。
总之,IoC可以帮助我们实现更好的解耦和更好的可维护性和可扩展性。
AOP(面向切面编程): 在传统的OOP编程中,我们通常会将功能划分为多个对象,并通过继承和组合来实现。但是,有些功能不适合在一个单独的对象中实现,比如日志记录、性能监控、事务管理等。这时,我们就需要使用AOP来将这些功能横向地应用于多个对象。
AOP通过在应用程序的不同层次上横向切割应用程序,将应用程序划分为多个切面,并通过将这些切面应用于不同的对象来实现这些横向的功能。AOP的核心是将这些横向功能从业务逻辑中分离出来,这样可以减少代码的冗余,提高代码的可维护性和可重用性。
在Java中,AOP通常通过代理模式实现。当一个对象被代理时,代理对象可以将横向功能注入到目标对象中。代理可以是静态代理或动态代理。静态代理需要手动编写代理类,而动态代理可以在运行时生成代理类,这样就可以更方便地实现AOP。
总之,AOP可以帮助我们实现更好的代码重用和更好的可维护性。使用AOP,我们可以将横向的功能从业务逻辑中分离出来,从而减少代码的冗余和重复。同时,AOP还可以提高代码的可重用性和可扩展性,因为它可以让我们将横向的功能应用于多个对象上。
综上所述,IoC和AOP都是现代Java应用程序开发中非常重要的技术。使用IoC可以帮助我们实现更好的解耦和更好的可维护性和可扩展性;而使用AOP可以帮助我们实现更好的代码重用和更好的可维护性。这些技术可以帮助我们构建更加健壮和可维护的应用程序。
4 1、跨域的原因
跨域是是因为浏览器的同源策略限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。
所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域。
5.1 如何解决跨域
JSONP
CORS
搭建Node代理服务器
Nginx反向代理
postMessage
Websocket
4微服务
1 springboot和springcloud区别
1、含义不同
springboot:一个快速开发框架,它简化了传统MVC的XML配置,使配置变得更加方便、简洁。
springcloud:是建立在SpringBoot上的服务框架,进一步简化了配置,它整合了一全套简单、便捷且通俗易用的框架。
2、作用不同
springboot:为了提供一个默认配置,从而简化配置过程。
springcloud:为了给微服务提供一个综合管理框架。
3、使用方式不同
springboot:可以单独使用。
springcloud:springcloud必须在springboot使用的前提下才能使用。
4、特征不同
springboot:
spring应用:通过调用静态 run() 方法创建独立的 Spring 应用程序。
Web应用程序:我们可以使用嵌入式Tomcat,Jetty或Undertow创建HTTP服务器。无需部署 WAR 文件。
外化配置:弹簧启动也提供基于产品的应用程序。它在不同的环境中也同样有效。
安全性:它是安全的,内置于所有HTTP端点的基本身份验证中。
应用程序事件和监听器:Spring Boot必须处理许多任务,应用程序所需的事件。添加用于创建工厂文件的侦听器。
springcloud:
智能路由和服务发现:在创建微服务时,有四个服务很重要。服务发现就是其中之一。这些服务相互依赖。
服务到服务调用:要连接所有具有序列的从属服务,请注册以调用终端节点。
负载均衡:将网络流量适当分配到后端服务器。
领导选举:应用程序作为第三方系统与另一个应用程序一起使用。
全局锁定:两个线程不能同时访问同一资源。
分布式配置和分布式消息传递
5、注释不同
springboot:
@SpringBootApplication:此注释可以找到每个spring引导应用程序。它由三个注释组成:@EnableAutoConfiguration;@Configuration;@ComponentScan。它允许执行Web应用程序而无需部署到任何Web服务器中。
@EnableAutoConfiguration:要么您使用的是低于1.1的spring boot版本,要么是@SpringBootApplication没有使用,那么需要此注释。
@ContextConfiguration:JUnit测试需要它。spring-boot 应用程序需要单元测试来测试其中的服务类。它加载SpringBoot上下文,但未提供完整的SpringBoot处理。
@SpringApplicationConfiguration:它具有相同的工作@ContextConfiguration但提供完整的springboot处理。它加载 Bean 以及启用日志记录并从 application.properties 文件
加载属性。@ConditionalOnBoot:它定义了几个条件注释:@ConditionalOnMissingBoot;@ConditionalOnClass;@ConditionalOnMissingClass;@ConditionalOnExpression;@ConditionalOnJav。
springcloud:Spring Cloud主要遵循5个主要注释:
@EnableConfigServer:此注释将应用程序转换为服务器,该服务器更多地用于应用程序以获取其配置。
@EnableEurekaServer:用于 Eureka Discovery Services 的此注释可用于查找使用它的服务。
@EnableDiscoveryClient:帮助此注释应用程序在服务发现中注册,发现使用它的其他服务。
@EnableCircuitBreaker:使用断路器模式在相关服务发生故障时继续运行,防止级联故障。此注释主要用于 Hystrix 断路器。
@HystrixCommand(回退方法=“ fallbackMethodName”):用于标记回退到另一种方法的方法,它们无法正常成功。
6、优势不同
springboot:
快速开发和运行独立的弹簧Web应用程序。
默认情况下,它在需要时配置Spring功能。它的豆子被初始化并自动连接。
它不需要基于 XML 的配置。直接嵌入Tomcat,Jetty以避免复杂的部署。
没有必要部署 WAR 文件。
springcloud:
提供云服务开发。
它是基于微服务的架构来配置。
它提供服务间通信。
it 基于Spring Boot模型。
7、组件不同
springboot:spring启动启动器,spring启动自动配置,spring启动执行器,spring启动 CLI,spring启动初始化。
springcloud:配置、服务发现、断路器、路由和消息传递、API 网关、跟踪、CI 管道和测试。
8、设计目的不同
springboot:springboot的设计目的是为了在微服务开发过程中可以简化配置文件,提高工作效率。
springcloud:springcloud的设计目的是为了管理同一项目中的各项微服务,因此二者是完全不同的两个软件开发框架。
9 springcloud五大组件:
1、Eureka实现服务治理;
2、Ribbon主要提供客户侧的软件负载均衡算法;
3、Hystrix断路器,保护系统,控制故障范围;
4、Zuul,api网关,路由,负载均衡等多种作用;
5、Config配置管理。
10 Mybatis一级缓存与二级缓存的区别
一级缓存:SqlSession级别的缓存,缓存的数据只在SqlSession内有效。
二级缓存:mapper级别的缓存,同一个namespace公用这一个缓存,所以对SqlSession是共享的,二级缓存需要我们手动开启。
5分布式
6高并发
7前端
8sql优化
1 避免使用select *
会全表扫描获取全部字段,
2 用union all代替union
sql语句使用union关键字后,可以获取排重后的数据。
而如果使用union all关键字,可以获取所有数据,包含重复的数据。
3 小表驱动大表
4 批量操作
5 多用limit
6 in中值太多
7 增量查询
8 高效的分页
9 用连接查询代替子查询
10 join的表不宜过多
11 join时要注意
12 控制索引的数量
13 选择合理的字段类型
14 提升group by的效率
9大数据量处理办法
redis相关
Redis 与 memcached 相比有哪些优势?
memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型
redis 的速度比 memcached 快很多 redis 的速度比 memcached 快很多
redis 可以持久化其数据 redis 可以持久化其数据
3、Redis 支持哪几种数据类型?
String、List、Set、Sorted Set、hashes
4、Redis 主要消耗什么物理资源?
内存。
5、Redis 有哪几种数据淘汰策略?
noeviction:返回错误当内存限制达到,并且客户端尝试执行会让更多内存被使用的命令。
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
缓存穿透
一般的缓存系统,都是按照 key 去缓存查询,如果不存在对应的 value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的 key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。
2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。
缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
如何避免?
1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
2:做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期
3:不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀
java线程相关
1、新建状态(New):新创建了一个线程对象。
2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于可运行线程池中,变得可运行,等待获取CPU的使用权。
3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。
4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
(一)、等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
(二)、同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
(三)、其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
阻塞:线程A等待线程B的数据,线程B等待线程A的数据,互相等待,就会陷入阻塞,这也是一种线程阻塞。
阻塞状态是正在运行的线程遇到某个特殊情况。例如,延迟、挂起、等待I/O操作完成等。 进入阻塞状态的线程让出CPU,并暂时停止自己的执行。线程进入阻塞状态后,就一直等待,直到引起阻塞的原因被消除,线程又转入就绪状态,重新进入就绪队列排队。
1.继承Thread类
写一个类去继承Thread类,重写其中的run()方法,然后调用start()方法启动线程。
2.实现Runnable接口
写一个类去实现Runnable接口,重写其中的run()方法;用用实现Runnable接口的对象作为参数实例化一个Thread对象,调用Thread类的start()方法来启动线程。
线程池
线程池创建的四种方法
Java通过Executors提供四种线程池,分别为:
1、使用newCachedThreadPool
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程
2、使用newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中
3、使用newSingleThreadExecutor
创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO,优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
4、使用newScheduledThreadPool
创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。
jdbc连接数据库的步骤:
1、加载jdbc驱动程序;
2、创建数据库的连接;
3、创建preparedStatement;
4、执行SQL语句;
5、遍历结果集;
6、处理异常,
关闭JDBC对象资源。
MySQL 中有哪几种锁
MySQL中有以下几种锁:
共享锁(Shared Lock):也称为读锁(Read Lock),允许多个事务同时持有共享锁,且不互斥。共享锁适用于读操作,不阻塞其他事务的读操作。123
排他锁(Exclusive Lock):也称为写锁(Write Lock),排他锁在事务对表进行更新、删除等写操作时使用。排他锁只允许一个事务持有,其他事务不能同时持有共享锁或排他锁。
表级锁(Table-level Lock):表级锁是对整张表进行锁定,可以分为两种类型:共享锁和排他锁。23
行级锁(Row-level Lock):行级锁是针对数据表中的行进行锁定,锁定指定的行,其他事务对同一行的其他操作会被阻塞。
页级锁(Page-level Lock):页级锁作用于表的页(通常是一组连续的数据行)。3
间隙锁(Gap Lock):间隙锁用于锁定某个范围内的数据,而不是具体的行,用于防止其他会话在某个范围内插入新数据,从而确保查询的一致性。
临键锁(Next-Key Lock):临键锁是一种组合了行级锁和间隙锁的锁类型,用于防止幻读(Phantom Read)和确保范围查询的一致性。
意向锁:意向锁(IS、IX)是InnoDB引擎操作数据之前自动加的,不需要用户干预;意向共享锁表示事务准备给数据行加入共享锁,意向排它锁表示事务准备给数据行加入排他锁。