Java 开发工程师 面试题
Posted IT_Holmes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 开发工程师 面试题相关的知识,希望对你有一定的参考价值。
文章目录
- 1. 注解@Transactional事务的实现
- 2. Spring事务的 4个隔离级别 + 7个传播行为
- 3. IOC的三种注入方式
- 4. aop的5个通知类型
- 5. 分布式锁的作用
- 6. 浏览器发起一个请求的过程
- 7. http协议
- 8. 有状态bean 和 无状态bean
- 9. options请求(跨域预检)
- 10. http的9种 常见的请求方式
- 11. 如何证明当前对象是单例的
- 12. 多线程下,如何解决成员变量
- 13. transient 关键字作用
- 14. servlet的 / 和 /* 的区别
- 15. 代码里面的 / 一般指的那些地方
- 16. jsp九大内置对象
- 17. SpringMVC容器和Spring容器
- 18. Spring拦截器 + 统一异常处理
- 19. 单例设计模式的 懒汉式 和 饿汉式
- 20. 工厂模式
- 21. Java的 assert 断言
- 22. Spring的Assert断言工具类
1. 注解@Transactional事务的实现
就是通过反射 + 动态代理实现!
2. Spring事务的 4个隔离级别 + 7个传播行为
记住它们会出现什么情况(脏读,虚读,不可重复读)。
大多数使用required,记住required的理念。
3. IOC的三种注入方式
最常用的set注入。
构造器注入。
命名空间p或者c注入。
见:https://blog.csdn.net/IT_Holmes/article/details/121818148
4. aop的5个通知类型
aop配置文件的两种形式:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
">
<bean id="serviceTest" class="com.itholmes.service.UserserviceImpl"></bean>
<bean id="abc" class="com.itholmes.abc"></bean>
<aop:config>
<aop:aspect ref="abc">
<aop:pointcut id="aa" expression="execution(* com.itholmes.service.*.*(..))"/>
<!--下面的method就是上面ref引用类的方法名。-->
<aop:after method="after" pointcut-ref="aa"/>
<aop:before method="before" pointcut-ref="aa"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="aa" throwing="e"/> <!--throwing 表示异常处理的方法的参数名 (可以不再异常通知中声明异常对象)-->
<aop:after-returning method="afterReturning" pointcut-ref="aa"/>
<aop:around method="around" pointcut-ref="aa"/>
</aop:aspect>
</aop:config>
</beans>
aop注解形式:
package com.itholmes.config;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class AdviceTest
@Pointcut("execution(* com.itholmes.service.*.*(..))")
//这里的test()方法必须有,就像是一个名字一样的标识。
public void pointcut()
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint)
System.out.println(joinPoint.getSignature().getName() + "前置通知---");
//2. 正常返回
@AfterReturning("pointcut()")
public void doAfterSuccess(JoinPoint joinPoint)
System.out.println(joinPoint.getSignature().getName() + "正常返回通知---");
//3. 异常返回(与正常返回是互斥关系)
@AfterThrowing("pointcut()")
public void doAfterError(JoinPoint joinPoint)
System.out.println(joinPoint.getSignature().getName() + "异常通知---");
//4. 环绕
@Around(value = "pointcut()", argNames = "pjp")
public Object doAround(ProceedingJoinPoint pjp)
Object[] args = pjp.getArgs();
Object result;
try
// Before
System.out.println(pjp.getSignature().getName() + "环绕前置通知---");
result = pjp.proceed(args);
// AfterReturning
System.out.println(pjp.getSignature().getName() + "环绕返回通知---");
catch (Throwable e)
// AfterThrowing
// System.out.println(pjp.getSignature().getName() + "环绕异常通知---");
throw new RuntimeException(e);
finally
// After
// System.out.println(pjp.getSignature().getName() + "环绕最终通知---");
return result;
//5. 后置通知(最终通知)
@After("pointcut()")
public void doAfter(JoinPoint joinPoint)
System.out.println(joinPoint.getSignature().getName() + "后置,也就是最终通知---");
不要忘记添加配置文件信息:
<bean id="annotationPointCut" class="com.itholmes.config.AdviceTest"></bean>
<aop:aspectj-autoproxy proxy-target-class="false"/>
明白正常返回 和 异常返回是互斥的。
后置(最终)通知,不管 有没有异常都会执行。
5. 分布式锁的作用
分布式锁:https://www.modb.pro/db/246339
分布式锁:https://blog.csdn.net/zhaisharap/article/details/122471322
多个用户操作同一个数据的时候,例如:快递员取货,多个快递员,去取都一件货物,这个时候就需要分布式锁解决。因为分布式它们不在一个系统中,因此就可以通过redis,zookeeper等完成分布式锁的效果。
6. 浏览器发起一个请求的过程
- 浏览器发送http协议请求。
- 先根据URL域名,去本地hosts文件查找是否有映射IP,没有就去dns域名解析,得到ip地址。
- 之后,客户端根据解析的IP地址,会进行tcp三次握手与服务器建立连接。
- 建立连接后,就开始向服务器发送请求。
- 服务器响应给浏览器。
- 最后,tcp的四次挥手断开连接。
7. http协议
http协议是无状态的,就是对于事务处理没有记忆能力。就是向服务器发起两次请求,服务器就不知道这两次http请求都来自同一个浏览器发出的。
cookie就是来解决http无状态的问题。
长连接,短连接,无连接:
无连接:限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
短连接:短连接是指一次请求和响应后,连接一会就关闭,这种方式可以节省资源。
长连接:从HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头加入这行代码:
Connection:keep-alive
HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
常见的几个请求头:
- Referer : 是 HTTP 请求header 的一部分,当浏览器(或者模拟浏览器行为)向web 服务器发送请求的时候,头信息里有包含 Referer 。比如我在www.google.com 里有一个www.baidu.com 链接,那么点击这个www.baidu.com ,它的header 信息里就有:
Referer=http://www.google.com
- content-type :请求参数类型。
- content-length : 请求参数的长度。
- user-agent : 记录一些本地信息,提供你所使用的浏览器类型及版本.操作系统及版本.浏览器内核.等信息的标识.。
- host : 域名地址 (或者IP + 端口号)
8. 有状态bean 和 无状态bean
bean5种作用域:分别是:singleton、prototype、request、session、gloabal session
有状态会话bean :每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;
一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
无状态会话bean :bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。
由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。
但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
每次通过Spring容器获取prototype定义的bean时,容器都将创建一个新的Bean实例,每个Bean实例都有自己的属性和状态,而singleton全局只有一个对象。
根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton作用域。
9. options请求(跨域预检)
HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为"*")使用该方法。(简而言之,就是可以用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法)。
这是因为在跨域的情况下,在浏览器发起"复杂请求"时主动发起的。跨域共享标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。
10. http的9种 常见的请求方式
–
HTTP1.0定义了三种请求方法:GET、POST、HEAD
HTTP1.1定义了六种请求方法:PUT、DELETE、PATCH、OPTIONS、CONNECT、TRACE
- get 请求指定页面的信息,并返回实体主体(幂等)
- post 向指定资源提交数据进行处理请求,数据存在请求体(非幂等)
- head 类似get,但不返回具体内容,用于获取报头(幂等)
- put 完整替换更新指定资源数据,没有就新增(幂等)
- delete 删除指定资源的数据(幂等)
- patch 部分更新指定资源的数据(非幂等)
- options 允许客户端查看服务器的支持的http请求方法
- connect 预留给能将连接改为管道的代理服务器
- trace 追踪服务器收到的请求,用于测试或诊断
11. 如何证明当前对象是单例的
打印一下this,判断一些地址是否相同。
12. 多线程下,如何解决成员变量
举个例子:我像设计一个小功能,知道当前接口已经被访问了多少次了,在controller层设计一个成员变量,通过这个成员变量达到一个计数效果。
对于多线程,上面的代码逻辑肯定会出现问题,如何解决?
- 加同步锁synchronized,但是效率低。
- AtomicInteger ageAtic = new AtomicInteger(0); 调用getAndIncrement方法或者decrementAndGet。 本质上atomicInteger使用的乐观锁来实现的。
AtomicInteger integer = new AtomicInteger(0);
int i = integer.getAndIncrement(); // +1 操作
int i1 = integer.decrementAndGet(); // -1 操作
- 对于不是计数的同样可以使用乐观锁来解决这类问题。
乐观锁:数据库里面有一个字段version,开始业务执行前先查询version,业务执行后根据version来进行update操作(乐观锁:sql语句层次version + 1 where version = #version。)
sql语句的修改丢失,也可以用悲观锁(select … for update)处理。
对于这种业务有增有减,就容易产生ABA问题。ABA问题:由A变成B,再由B编程了A。这种ABA问题。
13. transient 关键字作用
transient关键字标记的成员变量不参与序列化过程,transient关键字只能修饰变量,而不能修饰方法和类。
14. servlet的 / 和 /* 的区别
见:https://www.jb51.net/article/216853.htm
15. 代码里面的 / 一般指的那些地方
代码里面 /
都是指的如下地方:
将页面放到web-inf下面,就可以通过走servlet来安全访问。
16. jsp九大内置对象
17. SpringMVC容器和Spring容器
springmvc容器 与 spring容器是子父容器。 开始先扫描springmvc容器,因此一般springmvc.xml文件里面,最好不要扫描service的路径。
当然,Spring.xml文件就要扫描service层下的实现类,进而放到spring容器里面,是为了配置mybatis的增强事务。
上面不是绝对,如果把事务整合什么的也都放到springmvc,也是可以行得通的。
18. Spring拦截器 + 统一异常处理
见:https://blog.csdn.net/IT_Holmes/article/details/123089091?spm=1001.2014.3001.5502
19. 单例设计模式的 懒汉式 和 饿汉式
单例模式:
- 构造方法私有,属性私有。
- 写一个专门获取当前对象的方法,无论获取多少次始终都是一个对象。
package com.itholmes.config;
public class Singleton
private static Singleton singleton = new Singleton();
private Singleton()
//饿汉式
public static Singleton getSingleton()
return singleton;
package com.itholmes.config;
public class Singleton
private static Singleton singleton = null;
private Singleton()
//懒汉式
public static Singleton getSingleton()
if (singleton == null)
singleton = new Singleton();
return singleton;
20. 工厂模式
见:https://www.runoob.com/design-pattern/factory-pattern.html
21. Java的 assert 断言
1、assert condition;
这里condition是一个必须为真(true)的表达式。如果表达式的结果为true,那么断言为真,并且无任何行动
如果表达式为false,则断言失败,则会抛出一个AssertionError对象。这个AssertionError继承于Error对象,
而Error继承于Throwable,Error是和Exception并列的一个错误对象,通常用于表达系统级运行错误。
2、asser condition:expr;
这里condition是和上面一样的,这个冒号后跟的是一个表达式,通常用于断言失败后的提示信息,说白了,它是一个传到AssertionError构造函数的值,如果断言失败,该值被转化为它对应的字符串,并显示出来。
public class Test
public static void main(String[] args)
System.out.println("start");
assert true;
System.out.println("go on");
assert false:"stop";
System.out.println("end");
需要观察断言的运行情况,就需要打开系统类的assertion功能 ,我们可使用-esa参数打开,使用 -dsa参数关闭。 -esa和-dsa的全名为-enablesystemassertions和 -disenablesystemassertions,全名和缩写名有同样的功能。
22. Spring的Assert断言工具类
Spring的Assert断言工具类,通常用于数据合法性检查。位于 org.springframework.util.Assert包下,使用Assert可以使复杂的判断变得更加简单。
以上是关于Java 开发工程师 面试题的主要内容,如果未能解决你的问题,请参考以下文章