Java最新面试宝典 Spring面试题
- 前言
- 1、Spring是什么?
- 2、Spring 的优点?
- 3、什么是IOC?
- 4、什么是 AOP?
- 5、AOP 有哪些实现方式?
- 6、什么是DI依赖注入?
- 7、将一个类声明为Spring的 bean 的注解有哪些?
- 8、区分 BeanFactory 和 ApplicationContext?
- 9、Spring 中的 bean 的作用域有哪些?
- 10、Spring 中的 bean 生命周期?
- 11、Spring启动大概流程?
- 12、Spring中出现同名bean怎么办?
- 13、如何开启注解的依赖注入?
- 14、Spring如何解决循环依赖?
- 15、Spring中的事务是如何实现的?
- 16、Spring中事务失效情况?
- 17、Spring事务的传播机制?
- 18、Spring框架中的单例bean是线程安全的吗?
- 19、你用过哪些重要的Spring注解?
- 20、Spring事务的实现方式和实现原理?
- 总结
前言
最新的 Java 面试题,技术栈涉及 Java 基础、集合、多线程、Mysql、分布式、Spring全家桶、MyBatis、Dubbo、缓存、消息队列、Linux…等等,会持续更新。
如果对老铁有帮助,帮忙免费点个赞,谢谢你的发财手!
1、Spring是什么?
Spring是一个轻量级的IOC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。
主要包括以下七个模块:
Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
Spring Core:核心类库,所有功能都依赖于该类库,提供IOC和DI服务;
Spring AOP:面向切面服务;
Spring Web:提供了基本的面向Web的综合特性;
Spring MVC:提供面向Web应用的Model-View-Controller,即MVC实现。
Spring DAO:对JDBC的抽象封装,简化了数据访问异常的处理,并能统一管理JDBC事务;
Spring ORM:对现有的ORM框架的支持。
2、Spring 的优点?
(1)spring属于低侵入式设计,代码的污染极低;
(2)spring的DI机制将对象之间的依赖关系交由框架处理,降低了组件的耦合性;
(3)Spring提供了AOP技术,支持将一些通用任务,如安全、事务、日志等进行集中式管理,从而提供更好的复用。
(4)spring对于主流的应用框架提供了集成支持。
3、什么是IOC?
IOC,Inversion of Control,控制反转,指将对象的控制权转移给Spring框架,由 Spring 来负责控制对象的生命周期(比如创建、销毁)和对象间的依赖关系。
最直观的表达就是,以前创建对象的时机和主动权都是由自己把控的,如果在一个对象中使用另外的对象,就必须主动通过new指令去创建依赖对象。
而 IOC 则是由专门的容器来帮忙创建对象,将所有的类都在Spring 容器中登记,当需要某个对象时,只需告诉 Spring 容器,然后 Spring 就会把你想要的对象主动给你。
也就是说,控制对象生命周期的不再是引用它的对象,而是Spring容器,由 Spring 容器帮我们创建、查找和注入依赖对象,而引用对象只是被动的接受依赖对象,这叫控制反转。
4、什么是 AOP?
AOP即面向切面编程, 它与传统的OOP(面向对象编程) 相辅相成,支持将一些通用任务,如安全、事务、日志、权限等进行集中式管理,在 OOP 中, 我们以类(class)作为基本单元, 而 AOP 中的基本单元是Aspect(切面)。
5、AOP 有哪些实现方式?
实现 AOP 的技术,主要分为两大类:
静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类。
动态代理 - 分为2种:
JDK动态代理:是通过反射机制来生成动态代理类,并且要求目标类必须实现InvocationHandler接口。
CGLIB动态代理:如果目标类没有实现接口,那么Spring会选择使用CGLIB来动态代理。CGLIB( Code Generation Library ),是一个代码生成的类库,可以在运行时动态的生成某个类的子类。注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
6、什么是DI依赖注入?
在依赖注入中,我们不必创建对象,只需描述如何创建它们,我们也不必在代码中将组件和服务连接在一起,而是在配置文件描述中哪些组件需要哪些服务,由 IOC 容器将它们装配在一起。
通常,依赖注入可以通过2种方式完成,即:
1、构造函数注入
2、setter 注入。
7、将一个类声明为Spring的 bean 的注解有哪些?
- 1、基于注解配置
@Component ,@(Rest)Controller, @Service, @Repository,@Import - 2、基于配置类
通过@Configuration和@Bean 注解
@Configuration
public class RedisConfig {@Beanpublic StudentBean myStudent() {return new StudentBean();}
}
- 3、基于 xml 配置
xml配置文件包含许多 bean 定义,它们通常以 bean 标签开头。例如:
<bean id="studentbean" class="org.edureka.firstSpring.StudentBean"><property name="name" value="Edureka"></property>
</bean>
8、区分 BeanFactory 和 ApplicationContext?
- BeanFactory是Spring中⾮常核⼼的组件,表示Bean⼯⼚,可以⽣成和维护Bean;
- ApplicationContext继承了BeanFactory,所以ApplicationContext拥有BeanFactory所有的特点,也是⼀个Bean⼯⼚,但是ApplicationContext除了继承BeanFactory之外,还继承了其他接口(比如EnvironmentCapable、MessageSource、ApplicationEventPublisher),因此ApplicationContext还有获取系统环境变量、国际化、事件发布等功能,这是BeanFactory所不具备的。
9、Spring 中的 bean 的作用域有哪些?
singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建一个新的 bean 实例。
request : 每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
session : :在一个HTTP Session中,一个Bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
10、Spring 中的 bean 生命周期?
在我理解Spring Bean的生命周期,大致分为Bean的实例化、Bean的初始化、Bean的生存期和Bean的销毁四个阶段。
简单来说有下面几步:
1、Spring根据我们定义的注解(@component),找到相应的类,并将定义的信息保存起来。
2、将bean的定义发布到SpringIOC容器中,根据其实现的Aware接口设置依赖信息(主要是BeanNameAware接口(可以知道自己在容器中的名字),BeanFactoryAware(可以根据bean名称来获取Bean对象),ApplicationContextAware(可以获取Spring上下文信息))
3、接下来调用前置初始化方法postProcessBeforeInitialization方法,完成初始化前的相关工作,比如属性填充;
4、调用afterPropertiesSet方法,实现initialzingBean接口,去做一些初始化相关的自定义工作;
5、调用后置初始化方法postProcessAfterInitialization方法,完成初始化后的自相关工作,比如AOP;
6、到这里,Bean的初始化完成,就可以使用这个Bean对象了;
7、当Bean不再用到,便要销毁。销毁过程:如果实现了DisposableBean接口,则会调用destroy方法;若配置了destry-method属性,则会调用其自定义的销毁方法。
11、Spring启动大概流程?
UseService.class-> 无参构造函数-> 普通对象-> 依赖注入成员属性-> 初始化(afterPropertySet)成员方法-> 初始化后(AOP)
-> 生成代理对象-> 放入map<beanName, bean对象>。
12、Spring中出现同名bean怎么办?
- 1、同一个配置文件内同名的Bean,spring会报错
- 2、不同配置文件中存在同名Bean,后者覆盖前者
- 3、xml配置文件和注解存在同名Bean,xml配置文件优先级高于注解。
13、如何开启注解的依赖注入?
要使用 @Autowired,可以有以下两种方式来实现:
- 1、引入配置文件中的下引入 :
<context:annotation-config /> - 2、在配置文件中直接引入AutowiredAnnotationBeanPostProcessor
< bean class=“org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor”/>
14、Spring如何解决循环依赖?
循环依赖是指两个或多个 Bean之间互相持有对方的引用,循环依赖将会导致注入死循环。 比如:A依赖于B、B依赖于A
而 Spring 中设计了三级缓存来解决循环依赖问题,简单的说就是:
1、A创建过程中需要B,于是将A放到三级缓存里面,先去创建B;
2、B创建的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A,然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A;
3、此时B已经创建好了,将自己放到一级缓存里面(此时B里面的A依然是创建中状态),然后回来接着创建A,直接从一级缓存里面拿到B,然后A也创建好了,并将A放到一级缓存中,并删除二级缓存里的A。
其中,一级缓存:所有的成熟bean
二级缓存:原生的早期bean
三级缓存:代理的bean
Springboot可以通过@lazy注解懒加载解决。
15、Spring中的事务是如何实现的?
Spring事务底层是基于数据库事务和AOP机制,底层原理是这样的:
- ⾸先对于使⽤了@Transactional注解的Bean,Spring会创建⼀个代理对象,
当调⽤代理对象的⽅法时,会先判断该⽅法上是否加了@Transactional注解; - 如果加了,则创建⼀个数据库连接,并把它的⾃动提交(autocommit)改为false,然后放到ThreadLocal中;
- 如果该⽅法执行完后,没有出现异常就直接提交事务,如果出现了异常,就回滚事务。
3、Spring事务的隔离级别和传播机制 - Spring事务的隔离级别对应的就是数据库的隔离级别;
- Spring事务的传播机制是Spring自己实现的,默认是required;
- Spring事务的传播机制是基于数据库连接来做的,⼀个数据库连接对应⼀个事务,如果传播机制配置为required_new,那么实际上就是新建⽴⼀个数据库连接,这两个事务是互不影响的。
16、Spring中事务失效情况?
- 数据库引擎不支持事务
mysql存储引擎除了innodb,其它都不支持事务; - 类没有被spring管理
类没有加@Component注解,这个类就不会添加到Spring容器中; - 方法不是public修饰或者是final修饰
@Transactional只能用在public方法上面,因为底层cglib动态代理是通过继承来实现的; - 调用内部方法
调用内部方法不是代理类调用; - 抛出的异常被捕获
异常被try catch 捕获,Spring事务会认为没有出现异常; - 事务的传播机制配置错误
传播机制配置为required_new或者never - rollbackFor属性设置错误
默认是RuntimeException或error回滚,比如自定义异常没有继承RuntimeException
17、Spring事务的传播机制?
事务的传播机制是Spring框架实现的功能,是指事务方法A,被另外一个方法B调用的时候,对方法A有何种影响:
- PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中;
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起;
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
18、Spring框架中的单例bean是线程安全的吗?
不是线程安全的,当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这时多个线程会并发执行该请求多对应的业务逻辑(成员方法)。
可以通过ThreadLocal和线程同步机制解决共享变量问题。
19、你用过哪些重要的Spring注解?
@Controller -用于Spring MVC项目中的控制器类。@Service -用于服务类。
@RequestMapping -用于在控制器处理程序方法中配置URI映射。
@ResponseBody -用于发送Object作为响应,通常用于发送XML或JSON数据作为响应。@PathVariable -用于将动态值从URI映射到处理程序方法参数。
@Autowired -用于在spring bean中自动装配依赖项。
@Qualifier -使用@Autowired注解,以避免在存在多个bean类型实例时出现混淆。@Scope -用于配置spring bean的范围。
@Configuration,@ComponentScan和@Bean -用于基于java的配置。@Aspect,@Before,@After,@Around,@Pointcut -用于切面编程(AOP)。
20、Spring事务的实现方式和实现原理?
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务
功能的。真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
Spring支持两种类型的事务管理:
编程式事务管理:这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护。
声明式事务管理:这意味着你可以将业务代码和事务管理分离,你只需用注解和XML配置来管理事务。
总结
都已经看到这里啦,赶紧收藏起来,祝您工作顺心,生活愉快!