Java面试题超详细整理《Spring篇》,java类加载机制面试题

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

  • @ModelAttribute:该Controller的所有方法在调用前,限制性此方法,可用于注解和方法参数中,可以把这个ModelAttribute特性,应用在BaseController中,所有的Controller继承BaseCotroller,即可实现在调用Controller时,先执行@ModelAttribute方法。

@RestController与@Controller的区别是什么?


Controller 返回一个页面:单独使用 @Controller 不加 @ResponseBody的话一般使用在要返回一个视图的情况,这种情况属于比较传统的Spring MVC 的应用,对应于前后端不分离的情况。

在这里插入图片描述

@RestController (等价于@Controller +@ResponseBody)返回JSON 或 XML 形式数据:@RestController只返回对象,对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response)中,这种情况属于 RESTful Web服务,这也是目前日常开发所接触的最常用的情况(前后端分离)。

在这里插入图片描述

@ResponseBody 注解的作用是将 Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到HTTP 响应(Response)对象的 body 中,通常用来返回 JSON 或者 XML 数据,返回 JSON 数据的情况比较多。


@RequestMapping注解的属性


RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

RequestMapping注解有六个属性:

  • value: 指定请求的实际地址,指定的地址可以是URI Template 模式;

  • method: 指定请求的method类型, GET、POST、PUT、DELETE等;

  • consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json,text/html;

  • produces: 指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

  • params: 指定request中必须包含某些参数值是,才让该方法处理。

  • headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求


@Component 和 @Bean 的区别是什么?


  • 作用对象不同: @Component 注解作用于类,而@Bean注解作用于方法。

  • @Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用@ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了Spring这是某个类的示例,当我需要用它的时候还给我。

  • @Bean 注解比 Component 注解的自定义性更强,而且很多地方我们只能通过 @Bean 注解来注册bean。比如当我们引用第三方库中的类需要装配到 Spring容器时,则只能通过 @Bean来实现。

@Configuration

public class AppConfig {

@Bean

public TransferService transferService() {

return new TransferServiceImpl();

}

}

//上面的代码相当于下面的 xml 配置


@PathVariable和@RequestParam的区别


  • 请求路径上有个id的变量值,可以通过@PathVariable来获取 @RequestMapping(value =“/page/{id}”, method = RequestMethod.GET)

  • @RequestParam用来获得静态的URL请求入参 spring注解时action里用到。


@Autowired和@Resource之间的区别


  • @Autowired可用于:构造函数、成员变量、Setter方法,@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。

  • @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入。


Bean Factory和 Application Context有什么区别?


Applicationcontext是 Beanfactory的子接口,ApplicationContext提供了更完整的功能:

  • ①继承 Messagesource,因此支持国际化

  • ②统一的资源文件访问方式。

  • ③提供在监听器中注册bean的事件。

  • ④同时加载多个配置文件。

  • ⑤载入多个(有继承关系)上下文,使得每个上下文都专注于一个特定的层次,比如应用的web层。

加载方式:

  • Bean Factroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时调用 getbean(),才对该Bean进行加载实例化。这样,我们就不能发现一些存在的 Spring的配置问题。如果Bean的某一个属性没有注入, Beanfacotry加载后,直至第一次使用调用 getbean方法才会抛出异常。
  • Applicationcontext,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现 spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 Applicationcontext启动后预载入所有的单实例Bean,通过预载入单实例bean,确保当你需要的时候,不需要等待,直接使用。

创建方式:

Bean Factory通常以编程的方式被创建, Applicationcontext还能以声明的方式创建,如使用ContextLoader。

注册方式:

Bean Factory和 Application Context,都支持 Bean Postprocessor、 Beanfactory Postprocessor的使用,但两者之间的区别是: Beanfactory需要手动注册,而 Applicationcontext则是自动注册。

相对于基本的 Beanfactory, Applicationcontext唯的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。


ApplicationContext通常的实现是什么?


  • FileSystemXmlApplicationContext :此容器从一个XML文件中加载beans的定义,XML Bean 配置文件的全路径名必须提供给它的构造函数。

  • ClassPathXmlApplicationContext:此容器也从一个XML文件中加载beans的定义,这里,你需要正确设置classpath因为这个容器将在classpath里找bean配置。

  • WebXmlApplicationContext:此容器加载一个XML文件,此文件定义了一个WEB应用的所有bean


Spring 中的 bean 生命周期?


解析类-》加载对象-》依赖注入-》回调Aware方法-》后置处理器处理(初始化及初始化前后)-》使用-》销毁

  • Bean 容器解析类得到配置文件中 Spring Bean 的定义(BeanDefinition)。(解析)

  • Bean 容器利用 Java Reflection API 创建一个Bean的实例。(加载对象)

  • 如果涉及到一些属性值(加了@Autowride注解的属性)利用 set()方法给对象设置属性。(依赖注入)

  • 回调Aware方法:如果实现了其他 *.Aware接口,就调用相应的方法。(回调Aware方法)

①如果 Bean 实现了 BeanNameAware 接口,调用 setBeanName()方法,传入Bean的名字。

②如果 Bean 实现了 BeanClassLoaderAware 接口,调用 setBeanClassLoader()方法,传入 ClassLoader对象的实例。

  • 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor对象,执行postProcessBeforeInitialization() 方法。(后置处理器初始化前方法)

  • 如果Bean实现了InitializingBean接口,执行afterPropertiesSet()方法。(初始化方法)

  • 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。

  • 如果有和加载这个 Bean的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法。(后置处理器初始化后方法,会进行AOP)

  • 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。

  • 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。

图示:

在这里插入图片描述

后置处理器BeanPostProcessor :在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。后置处理器分为 Bean Factory后置处理器(视线了Spring的扫描)和Bean后置处理器(实现了@ Autowired注解的属性自动赋值、AOP)

bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解


Spring 中的 bean 的作用域有哪些?


  • singleton(单例模式,默认) : 每个容器中只有一个bean的实例,单例的模式由 Beanfactory自身来维护。该对象的生命周期是与 Spring IOC容器一致的(但在第一次被注入时才会创建)。

  • prototype (原型模式): 每次请求都会创建一个新的 bean 实例。在每次注入时都会创建个新的对象

  • request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。

  • session:每一次HTTP请求都会产生一个新的 bean,该bean仅在当前 HTTP session 内有效。

  • application:bean被定义为在 Servletcontext的生命周期中复用一个单例对象(可以实现跨容器)

  • global-session: 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。Portlet是能够生成语义代码片段的小型Java Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。


Spring 中的单例 bean 线程安全吗?


存在安全问题的。Spring中的bean默认是单例模式的,框架并没有对bean进行多线程的封装处理,当多个线程操作同一个对象的时候,对这个对象的成员变量的写操作会存在线程安全问题。

但是大多数bean都是无状态的(不具有数据存储功能),比如说controller、 service和dao层,我们一般只是调用里面的方法,多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。但是dao层会操作数据库 Connection, Connection是带有状态的,比如说数据库事务, Spring的事务管理器,需要我们进行处理。

因此,不要在bean中声明任何有状态的实例变量或类变量,如果必须如此,可以参考一下方案:

  • 使用 Threadloca把变量变为线程私有的,比如在dao层,可以使用Threadlocal为不同线程维护了一套独立的 connection副本,保证线程之间不会互相影响。

  • 改变 Bean 的作用域为 “prototype”:每次请求都会创建一个新的 bean 实例,自然不会存在线程安全问题。

  • 如果bean的实例变量或类变量需要在多个线程之间共享,那么就只能使用 synchronized、OCK、CAS等这些实现线程同步的方法了。


Spring 框架中用到了哪些设计模式?


  • 工厂设计模式: 由一个工厂类根据传入的参数,动态决定创建那个产品类。Spring使用工厂模式通过 BeanFactory、ApplicationContext 创建bean 对象。

  • 单例设计模式 : 保证一个类仅有一个实例,并提供一个访问它的全局访问点。Spring 中的 Bean 默认都是单例的。

  • 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式(HandlerAdapter)适配Controller,对应的每一种Controller都有一种对应的适配器实现类。

  • 代理设计模式 : Spring AOP 功能的实现。AOP把切面应用到对象并创建新的代理对象。

  • 观察者模式:Spring的事件驱动模型使用的是观察着模式,Spring中Observer模式常用的地方是Listener的实现

  • 策略模式:Spring框架的资源访问Resource接口。该接口提供了更强的资源访问能力,Spring框架本身大量使用了Resource的接口来访问底层资源。

  • 装饰器模式:动态地给一个对象添加额外的职责。Spring中类名包括Wrapper或Decorator使用了装饰器模式。

  • 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。

  • 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。


Spring事务的实现方式


Spring 管理事务的方式有几种?

  • 编程式事务,在代码中硬编码。(不推荐使用)

  • 声明式事务,在配置文件中配置(推荐使用)

声明式事务又分为:

  • 基于XML的声明式事务

  • 基于注解的声明式事务

说一下 Spring的事务机制

  • spring事务底层是基于数据库事务和AOP机制的(事务这个概念是数据库层面的, Spring只是基于数据库中的事务进行了扩展)

  • 首先对于使用了@Transactional注解的bean,Spring会创建一个代理对象作为Bean

  • 当调用代理对象的方法时,会先判断该方法上是否加了@ Transactional注解

  • 如果加了,那么则利用事务管理器创建一个数据库连接,并把事务的自动提交设置为 false,然后再去执行原本的业务逻辑方法(sql)。

  • 如果执行业务逻辑方法没有出现异常,那么代理逻辑中就会将事务进行提交

  • 如果执行业务逻辑方法出现了异常,那么则会将事务进行回滚

  • 针对哪些异常回滚事务是可以配置的,可以利用@Transactional注解中的 rollbackfor属性进行配置,默认情况下会对 Runtimeexception和Error进行回滚。

  • Spring事务的隔离级别对应的就是数据库的隔离级别

  • Spring事务的传播机制是 Spring事务自己实现的,也是 Spring事务中最复杂的

  • Spring事务的传播机制是基于数据库连接来做的,一个数据库连接一个事务,如果传播机制配置为需要新开个事务,那么实际上就是先建立一个数据库连接,在此新数据库连接上执行sql


@Transactional注解了解吗?


Exception分为运行时异常RuntimeException和非运行时异常。事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。

当@Transactional注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

@Transactional(rollbackFor = Exception.class):

在@Transactional注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚。


spring事务什么时候会失效?


spring事务的原理是AOP,进行了切面增强,那么失效的根本原因是这个AOP不起作用了。常见情况有如下几种:@Transactional标识的方法只有被代理对象调用时,注解才会生效

  • 发生自调用,类里面使用this调用本类的方法,此时这个this对象不是代理类,而是Userservice对象本身(解决方法很简单,让那个this变成 Euserservice的代理类即可)

  • 方法不是public的,Transactional只能用于public的方法上,否则事务不会失效,如果要用在非public方法上,可以开启( Aspectj代理模式)。

  • 异常被吃掉,事务不会回滚或者抛出的异常没有被定义,默认为 RuntimeException。


Spring 事务中的隔离级别有哪几种?


spring事务隔离级别就是数据库的隔离级别:外加一个默认级别

  • isolation_default(默认级别):使用后端数据库默认的隔离级别

  • read_uncommitted(读未提交读):最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

  • read_committed(读以提交、不可重复读):允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

  • repeatable_read(可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

  • serializable(可串行化):最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

数据库的配置隔离级别是 Read Commited,而 Spring配置的隔离级别是 Repeatable Read,请问这时隔离级别是以哪个为准?

以 Spring配置的为准,如果 spring设置的隔离级别数据库不支持,效果取决于数据库


Spring 事务中哪几种事务传播行为?


多个事务方法相互调用时事务如何在这些方法间传播:

方法A是一个事务的方法,方法A执行过程中调用了方法B,那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响,同时方法A的事务对方法B的事务执行也有影响,这种影响具体是什么就由两个方法所定义的事务传播类型所决定。

  • REQUIRED(Spring默认的事务传播类型):如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务

  • SUPPORTS:当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行

  • MANDATORY:当前存在事务,则加入当前事务,如果当前事务不存在,则拋出异常

  • REQUIRES_NEW:创建一个新事务,如果存在当前事务,则挂起该事务

  • NOT_SUPPORTED:以非事务方式执行如果当前存在事务,则挂起当前事务

  • NEVER:不使用事务,如果当前事务存在,则抛出异常

  • NESTED:如果当前事务存在,则在嵌套事务中执行,否则 REQUIRED的操作一样(开启一个事务)

NESTED和 REQUIRES_NEW的区别:

REQUIRES_NEW是新建一个事务并且新开启的这个事务与原有事务无关,而 NESTED则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务)。在 NESTED情况下父事务回滚时,子事务也会回滚,而在REQUIRES_NEW情况下,原有事务回滚,不会影响新开启的事务

NESTED和 REQUIRED的区别:

REQUIRED情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用方出现异常时,由于共用一个事务,所以无论调用方是否 catch其异常,事务都会回滚而在 NESTED情况下,被调用方发生异常时,调用方可以 catch其异常,这样只有子事务回滚,父事务不受影响。

最后

每年转战互联网行业的人很多,说白了也是冲着高薪去的,不管你是即将步入这个行业还是想转行,学习是必不可少的。作为一个Java开发,学习成了日常生活的一部分,不学习你就会被这个行业淘汰,这也是这个行业残酷的现实。

如果你对Java感兴趣,想要转行改变自己,那就要趁着机遇行动起来。或许,这份限量版的Java零基础宝典能够对你有所帮助。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
用方是否 catch其异常,事务都会回滚而在 NESTED情况下,被调用方发生异常时,调用方可以 catch其异常,这样只有子事务回滚,父事务不受影响。

最后

每年转战互联网行业的人很多,说白了也是冲着高薪去的,不管你是即将步入这个行业还是想转行,学习是必不可少的。作为一个Java开发,学习成了日常生活的一部分,不学习你就会被这个行业淘汰,这也是这个行业残酷的现实。

如果你对Java感兴趣,想要转行改变自己,那就要趁着机遇行动起来。或许,这份限量版的Java零基础宝典能够对你有所帮助。

[外链图片转存中…(img-xzbie7i6-1713420027933)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-NYth9xmY-1713420027933)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值