2022春招如期而至,针对最近有面试的同学我也是呕心沥血整理了春招系列文章,力求把面试的各个方面都给好兄弟们捋清楚,算法和实战项目推荐我前两天已经写了,有兴趣的同学可以去瞅瞅
篇幅所限,关于Java框架面试我也不可能全写完了,只能挑一些基础与比较有代表性的写一写,有同学就会说了,光讲这些理论有什么用,这些谁不知道,能帮我拿到offer吗?
别急,我早就预判了你的预判,这两年的各大厂Java岗面试真题我都有在收集整理,去芜存菁之后分门别类给你们弄好了,如图
需要的同学转发本文+关注+私信【310】即可获取
好了,话不多说,直接开始正文
概念
spring是个java企业级应用的开源框架。spring主要用来开发java应用,但是有些扩展是针对
J2EE平台的文本应用。Spring框架目标是简化java企业级应用的开发,并通过pojo为基础的
编程模型促进良好的编程习惯。
优点
AOP(可以说是对oop的补充和完善)它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
关键点:
IOC(控制反转)意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。IOC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。
依赖注入方式
DI(依赖注入)组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
Spring Bean的作用域
常用注解
Spring支持两种类型的事务管理
事务管理的优点
SpringMVC是一个基于MVC架构的用来简化web应用程序开发的应用开发架构,他是spring的一个模块,无需中间整合层来整合,他和Struts2一样都属于表现层的框架。在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
用户发送请求至前端控制器DispatcherServlet;
DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
DispatcherServlet通过HandlerAdapter处理器适配器调用处理器;执行处理器(Handler,也叫后端控制器);
Handler执行完成返回ModelAndView;
HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
ViewResolver解析后返回具体View;
DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
DispatcherServlet响应用户。
优点
相关注解
@Conntroller: 用于控制层注解,不能用用别的注解代替;
@RequestMapping: 用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径(method=RequestMethod.GET)。
@ResponseBody: 将内容或对象作为 HTTP 响应正文返回,并调用适合HttpMessageConverter的Adapter转换对象,写入输出流;
@RequestBody:将HTTP请求正文转换为适合的HttpMessageConverter对象;
@SessionAttributes:用来在controller内部共享model属性的;
@RequestParam:绑定单个请求参数值;
@PathVariable:绑定URI模板变量值;
@ModelAttribute:可以应用在方法参数上或方法上,他的作用主要是当注解在方法参数上时会将注解的参数对象添加到Model中;当注解在请求处理方法Action上时会将该方法变成一个非请求处理的方法,但其它Action被调用时会首先调用该方法。
@Component:在类定义之前添加@Component注解,他会被spring容器识别,并转为bean;
@Repository:对dao实现类进行注解;
@Service:用于对业务逻辑层进行注解;
Spring Boot 是 Spring 开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
优点
核心配置文件
相关注解
@SpringBootApplication:启动类上面的注解,是springboot的核心注解;
@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能;
@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能:@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class });
@ComponentScan:Spring组件扫描。
JavaConfig
Spring JavaConfig是Spring社区的产品,它提供了配置Spring IoC容器的纯Java方法。因此
它有助于避免使用XML配置。
JavaConfig的优点:
微服务
微服务是指开发一个单个小型的但有业务功能的服务,每个服务都有自己的处理和轻量通讯机制,可以部署在单个或多个服务器上。微服务也指一种种松耦合的、有一定的有界上下文的面向服务架构。也就是说,如果每个服务都要同时修改,那么它们就不是微服务,因为它们紧耦合在一起;如果你需要掌握一个服务太多的上下文场景使用条件,那么它就是一个有上下文边界的服务,这个定义来自DDD领域驱动设计。相对于单体架构和SOA,它的主要特点是组件化、松耦合、自治、去中心化,体现在以下几个方面:
核心组件
优点
服务注册与发现
服务在发布时指定对应的服务名(服务名包括了IP地址和端口)将服务注册到注册中心
(eureka、zookeeper等),这一过程是springcloud自动实现 只需要在main方法添加
@EnableDisscoveryClient同一个服务修改端口就可以启动多个实例调用方法:传递服务名称
通过注册中心获取所有的可用实例 通过负载均衡策略调用(ribbon和feign)对应的服务。
Ribbon和Feign区别
断容器的作用
当一个服务调用另一个服务由于网络原因或者自身原因出现问题时调用者就会等待被调用者的
响应当更多的服务请求到这些资源时,导致更多的请求等待这样就会发生连锁效应(雪崩效
应)断路器就是解决这一问题。
断路器有三种状态:
微服务之间独立通信
远程过程调用(Remote Procedure Invocation):也就是我们常说的服务的注册与发现,直
接通过远程过程调用来访问别的service。
消息:使用异步消息来做服务间通信,服务间通过消息管道来交换消息,从而通信。
负载均衡
负载均衡可以改善跨计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器等多种计算资源的工作负载分布。负载均衡旨在优化资源使用,最大吞吐量,最小响应时间并避免任何单一资源的过载。使用多个组件进行负载均衡而不是单个组件可能会通过冗余来提高可靠性和可用性。
负载平衡通常涉及专用软件或硬件,例如多层交换机或域名系统服务进程。
Dubbo是一个由阿里巴巴开源的、分布式的RPC(Remote Procedure Call Protocol-远程过
程调用)和微服务框架,现已成为Apache基金会孵化项目。Dubbo提供了三个关键功能:基于
接口的远程调用,容错与负载均衡,服务自动注册与发现。
支持的协议
dubbo(推荐):Dubbo 缺省协议是dubbo协议,采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低;
rmi:RMI协议采用阻塞式(同步)短连接和 JDK 标准序列化方式。适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件;
hessian:Hessian底层采用Http通讯(同步),采用Servlet暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现。适用于传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件;
http:基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现;
webservice:基于 WebService 的远程调用协议,基于 ApacheCXF的 frontend-simple 和 transports-http 实现;
thrift:当前dubbo支持的thrift协议是对thrift原生协议的扩展,在原生协议的基础上添加了一些额外的头信息,比如 service name,magic number 等。使用 dubbo thrift 协议同样需要使用 thrift 的 idl compiler 编译生成相应的 java 代码,后续版本中会在这方面做一些增强;
memcached:基于 memcached实现的RPC协议 ;
redis:基于Redis实现的RPC协议。
Dubbo允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议。
Dubbo和SpringCloud的区别
两个没关联,如果硬要说区别,有以下两点:
在Provider上可以配置的Consumer端的属性有哪些
Dubbo推荐使用什么序列化框架
推荐使用Hessian序列化,还有Duddo、FastJson、Java自带序列化。
通信框架
Dubbo默认使用Netty框架,也是推荐的选择,另外内容还集成有Mina、Grizzly。
Dubbo服务之间的调用
默认是同步等待结果阻塞的,支持异步调用。
Dubbo是基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小,异步调用会返回一个Future对象。
如何优雅停机
Dubbo是通过JDK的ShutdownHook来完成优雅停机的,所以如果使用kill -9 PID等强制关闭
指令,是不会执行优雅停机的,只有通过kill PID时,才会执行。
服务读写推荐的容错策略
服务暴露的过程
Dubbo会在Spring实例化完bean之后,在刷新容器最后一步发布ContextRefreshEvent事件的时候,通知实现了ApplicationListener的ServiceBean类进行回调onApplicationEvent事件方法,Dubbo会在这个方法中调用ServiceBean父类ServiceConfig的export方法,而该方法真正实现了服务的(异步或者非异步)发布。
服务注册
以zookeeper为例
支持以下功能:
集群容错方案
负载均衡策略
mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。
优点
简单易学,容易上手(相比于Hibernate) —- 基于SQL编程;
JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持,而JDBC提供了可扩展性,所以只要这个数据库有针对Java的jar包就可以就可以与MyBatis兼容),开发人员不需要考虑数据库的差异性。
提供了很多第三方插件(分页插件 / 逆向工程);
能够与Spring很好的集成;
MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,解除sql与程序代码的耦合,便于统一管理和优化,并可重用。
提供XML标签,支持编写动态SQL语句。
提供映射标签,支持对象与数据库的ORM字段关系映射。
提供对象关系映射标签,支持对象关系组建维护。
缺点
Xml映射文件与Mapper接口的工作原理
Mapper接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。
Mybatis的一级、二级缓存
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开
二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置
对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
编程步骤
#{}和${}的区别
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一
个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的zookeeper机器来处理。对于写请求,这些请求会同时发给其他
zookeeper机器并且达成一致后,请求才会返回成功。因此,随着zookeeper的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。
有序性是zookeeper中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个
唯一的时间戳,这个时间戳称为zxid(Zookeeper Transaction Id)。而读请求只会相对于更
新有序,也就是读请求的返回结果中会带有这个zookeeper最新的zxid。
工作原理
Zookeeper 的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和 leader的状态同步以后,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
特点
通知机制
client端会对某个znode建立一个watcher事件,当该znode发生变化时,这些client会收到zk
的通知,然后client可以根据znode变化来做出业务上的改变等。
四种类型的znode
PERSISTENT-持久化目录节点 :客户端与zookeeper断开连接后,该节点依旧存在 ;
PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号 ;
EPHEMERAL-临时目录节点:客户端与zookeeper断开连接后,该节点被删除 ;
EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点:客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
Server的工作状态
Docker是一个容器化平台,它以容器的形式将您的应用程序及其所有依赖项打包在一起,以
确保您的应用程序在任何环境中无缝运行。
与虚拟机有何不同
Docker不是虚拟化方法。它依赖于实际实现基于容器的虚拟化或操作系统级虚拟化的其他工
具。为此,Docker最初使用LXC驱动程序,然后移动到libcontainer现在重命名为runc。
Docker主要专注于在应用程序容器内自动部署应用程序。应用程序容器旨在打包和运行单个
服务,而系统容器则设计为运行多个进程,如虚拟机。因此,Docker被视为容器化系统上的
容器管理或应用程序部署工具。
Docker镜像
Docker镜像是Docker容器的源代码,Docker镜像用于创建容器。使用build命令创建镜像。
Docker容器
Docker容器包括应用程序及其所有依赖项,作为操作系统的独立进程运行。
容器的四种状态
Dockerfile中最常见的指令
常用命令
容器与主机之间的数据拷贝命令
docker cp 命令用于容器与主机之间的数据拷贝
主机到容器:
docker cp /www 96f7f14e99ab:/www/
容器到主机:
docker cp 96f7f14e99ab:/www /tmp/
监控Docker
一些常见的Docker事件是:attach,commit,die,detach,rename,destroy等。我们还可以使用各种选项来限制或过滤我们感兴趣的事件
Jenkins是一个开源的、可扩展的持续集成、交付、部署(软件/代码的编译、打包、部署)的
基于web界面的平台。允许持续集成和持续交付项目,无论用的是什么平台,可以处理任何类
型的构建或持续集成。
优点
Jenkins是一种使用Java编程语言编写的开源持续集成软件工具,用于实时测试和报告较大代码库中的孤立更改。Jenkins软件使开发人员能够快速找到并解决代码库中的缺陷,并自动进行构建测试。
CI/CD