1.Spring是什么?
Spring是一个轻量级的IoC和AOP容器框架。是为Java应用程序提供基础性服务的一套框架,目的是用于简化企业应用程序的开发,它使得开发者只需要关心业务需求。常见的配置方式有三种:基于XML的配置、基于注解的配置、基于Java的配置。
主要由以下几个模块组成:
- Spring Core:核心类库,提供IOC服务;
- Spring Context:提供框架式的Bean访问方式,以及企业级功能(JNDI、定时任务等);
- Spring AOP:AOP服务;
- Spring DAO:对JDBC的抽象,简化了数据访问异常的处理;
- Spring ORM:对现有的ORM框架的支持;
- Spring Web:提供了基本的面向Web的综合特性,例如多方文件上传;
- Spring MVC:提供面向Web应用的Model-View-Controller实现。
2.spring的设计核心是什么?
Spring的设计核心是控制反转(IoC)和面向切面编程(AOP),这两个核心特性共同构成了Spring框架的基础,使得应用开发更加模块化、灵活和易于维护。
- 控制反转(IoC)
- 控制反转(Inversion of Control,IoC)是Spring框架的核心理念之一。IoC的核心思想是将对象的创建权交给Spring容器来管理,而不是由开发者在代码中直接创建。这样做的好处是降低了代码之间的耦合度,使得各个组件之间的依赖关系更加清晰和灵活。
- 在IoC容器中,开发者只需要定义组件(Bean)的配置元数据,由容器负责实例化、装配和管理这些组件。这样,当需求发生变化时,只需要修改配置元数据,而不需要修改代码,从而提高了代码的可维护性和可扩展性。
- IoC的实现方式主要有两种:依赖注入(Dependency Injection,DI)和依赖查找(Dependency Lookup)。其中,依赖注入是Spring中最常用的方式,它可以通过构造器注入、Setter注入等方式将依赖关系注入到对象中。
- 面向切面编程(AOP)
- 面向切面编程(Aspect-Oriented Programming,AOP)是Spring框架的另一个核心特性。AOP允许开发者将横切关注点(如日志、事务管理等)从业务逻辑中分离出来,并在运行时动态地将它们织入到业务逻辑中。这样做的好处是减少了代码重复,提高了代码的可维护性和可重用性。
- 在Spring中,AOP可以通过使用代理模式来实现。SpringAOP支持两种类型的代理:JDK动态代理和CGLIB代理。其中,JDK动态代理只能代理实现了接口的类,而CGLIB代理可以代理没有实现接口的类。
3.IOC是什么?
控制反转,将创建对象进行反转,因为正常都是程序员去创建对象,现在使用spring容器去创建,根据需求自动去创建对象。对象实例化,通过spring容器进行创建和管理,spring通过DI(数据注入)实现IOC。
4.IOC的实现原理是什么?
实现原理是工厂模式加反射机制。
5.AOP是什么?
AOP也是以IOC为基础,面向切面编程,抽象化的面向对象,面向对象的补充和完善。面向对象就是把事务的特性和行为抽象为一个对象,比如:people类都有身高、年龄、体重等属性,也有吃饭、睡觉等行为。这些属性和行为封装成一个类。面向切面就像people类有自己的属性和行为,但是有一小部分人要去篮球场练习两年半,不是所有人都需要去练习篮球。那么AOP就把练习篮球的业务逻辑抽离出来,然后动态切入方法中,减少代码重复和解耦。简单来说:做到核心业务和非核心业务的耦合。
6.AOP的原理是什么?
AOP的实现原理是JDK动态代理, 代理模式是指给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理对象提供与真实对象相同的接口,以便代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作。
注意: 也可以使用CGLIB代理,基于类,JDK动态代理,基于接口。
7.AOP的应用场景?
- 日志记录
- 事务
- 权限管理
- 缓存
- 懒加载
- 内容传递
- 错误处理
- 调试
- 性能优化
- 持久化
- 资源池
- 同步
- 记录跟踪 优化 校准
8.说一下AOP都有哪些基本理念?
- 目标对象(target)
- 需要被代理的类。
- 连接点(JoinPoint)
- 程序执行的某一个点,比如某个方法。
- Aspect(切面)
- 通常是一个类,里面定义Pointcut(切入点)和 Advice(通知)。
- Pointcut(切入点)
- 用来指定需要将Advice(通知)使用到哪些地方。
- Advice(通知)
- 所要增强或增加的功能。
- weave(织入)
- 把切面应用到目标对象并创建新的代理对象的过程.
- introduction(引入)
- 在不修改代码的前提下,引入可以在运行期为类动态地增加一些方法或字段。
9.通知的类型有哪些
- 前置通知(Before Advice): 在目标方法执行之前执行。
- 后置通知(After Advice): 在目标方法执行之后执行 。
- 环绕通知(Around): 在目标方法调用前后均可执行自定义逻辑。
- 返回通知(After returning advice):在目标方法返回结果之后执行。
- 异常通知(After throwing advice): 异常通知, 在方法抛出异常之后。
10.Spring的优点和缺点
- 优点:
- 解耦和方便开发:spring容器进行对象的创建和管理。
- AOP的支持:面向切面编程,实现日志和权限拦截等功能。
- 声明事务的支持:通过配置进行事务管理,不需要手动编写。
- 方便集成各种框架。
- 缺点:
- 使用大量反射机制,占内存,不如直接调用效率高。
- 没有做到依赖管理。
- 集成的框架耦合度高,不易拆分。
11.Spring中Bean的注入方式
- 构造器注入
- Setter注入
- 接口注入(灵活性和易用性差,Spring4已经废弃)
- 注解注入
12.BeanFactory 和 ApplicationContext有什么区别?
- 是spring的核心接口,都可以作为容器,ApplicationContext是BeanFactory的子接口。
- BeanFactory: 是spring最底层的接口,包含各种Bean的定义和Bean的管理。
- ApplicationContext: 作为BeanFactory的派生,除了有BeanFactory的功能以外,还提供了更多的功能。
- 区别:
- BeanFactroy采用的是延迟加载形式来注入Bean的,使用到bean才会加载。ApplicationContext一次性加载所有bean。
- BeanFactory需要手动注册,而ApplicationContext则是自动注册。
- BeanFactory不支持国际化,ApplicationContext支持国际化(实现MessageSource接口)。
13.循环依赖的情况,怎么解决?
循环依赖:A依赖B,B依赖C,C依赖A,形成了闭环。
- 构造器的循环依赖: 这种依赖spring是处理不了的,直接抛出异常。
- 单例模式下的setter循环依赖:通过"三级缓存"处理循环依赖,能处理。
- 多例模式下的setter循环依赖: 不能处理,会一直产生新的Bean,导致OOM。
14.Spring中单例Bean是线程安全的吗?
不是,因为所有线程共享一个单例Bean,存在资源的竞争所以是线程不安全的,实际上大部分时间Bean是无状态的,所以说在某种程度上来说Bean其实是安全的。如果是有状态,那就需要开发人员修改bean的作用域。singleton改为prototype。
- 有状态: 有数据存储功能。
- 无状态: 不会保存数据。
15.Spring如何处理线程的并发问题?
- 把成员变量写在方法内。
- 使用ThreadLocal,ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。
- 修改bean的作用域,singleton改为prototype。(@Scope(“prototype”))
- 使用synchronized修饰。
16.Spring中Bean的生命周期
- bean: 是由 Spring IoC 容器实例化、组装和管理的对象。
- 正常情况: 当bean不在被使用,就会被回收。
- 单例模式: spring中bean的生命周期分为:实例化Bean->Bean属性填充->初始化Bean->销毁Bean。
- 多例模式: spring无法进行管理,所以将生命周期交给用户控制。
17.Spring用到了那些设计模式?
- 工厂模式: beanFactory就用到了简单工厂模式。
- 单例模式: Bean默认为单例模式。
- 代理模式: AOP用到了JDK的动态代理模式。
- 模板模式: 减少代码冗余,JDBC模板等。
- 观察者模式:定义对象间的一对多的关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。spring监听器的实现就用了观察者模式。
18.Spring的常用注解
@Component(任何层)
@Controller(表现层)
@Service(逻辑层)
@Repository(持久层): 被修饰的类,会被spring扫描到并注入到bean容器中(实例化对象)。
@Scope: 设置spring的作用域。
@Bean: 用于将方法返回值对象放入容器。
@Import: 在一个配置类中导入其它配置类的内容。
@AutoWired: 按照类型匹配注入。
@Qualifier: 和AutoWired联合使用,在按照类型匹配的基础上,在按照名称匹配。
@Resource: 按照名称匹配依赖注入。
@Configuration: 被此注解标注的类,会被 Spring 认为是配置类。
@ComponentScan: 用于对组件(Component)进行扫描。
@Transactional: 可以用于类和方法上,具有事务管理的功能
@Value: 将外部的值动态注入到 Bean 中。
@Value(“${}”):可以获取配置文件的值。
@Value(“#{}”):表示SpEl(Spring Expression Language是Spring表达式语言,可以在运行时查询和操作数据。)表达式通常用来获取 bean 的属性,或者调用 bean 的某个方法。
19.Spring 事务实现方式有哪些?
- 编程式: beginTransaction()、commit()、rollback()等事务管理相关的方法,灵活度高,但是维护性差。
- 声明式: 利用注解或者xml配置,将业务和事务分离出来。
20.Spring事务的实现方式和实现原理
Spring事务就是对数据库事务的支持,没有数据库的事务支持,Spring是无法提供事务功能的。
原理:Spring事务的实现原理主要基于控制反转(IoC)和面向切面编程(AOP)的思想,通过Spring框架提供的事务管理接口和AOP技术,实现对数据库事务的自动化管理。
21.说一下 Spring 的事务隔离?
- ISOLATION_DEFAULT: 默认值,使用数据库的隔离级别。
- ISOLATION_READ_UNCOMMITTED: 读未提交。
- ISOLATION_READ_COMMITTED: 读已提交。
- ISOLATION_REPEATABLE_READ: 可重复读。
- ISOLATION_SERIALIZABLE: 序列化。
22.Spring事务的传播行为
- REQUIRED(默认):默认事务传播行为,存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。
- REQUIRE_NEW:它不管是否存在事务,它都会新开启一个事务来执行,新老事务相互独立的,外部事务抛出异常,并不会影响内部事务的一个正常提交。
- NESTED:如果当前存在事务,就嵌套当前事务中去执行,如果当前没有事务,那么就新建一个事务,类似
- REQUIRE_NEW这个样一个传播行为。 SUPPORTS:表示支持当前当前的事务,如果当前不存在事务,就以非事务的方式去执行。
- NOT_SUPPORT: 总是非事务地执行,并挂起任何存在的事务。
- MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
- NEVER:就是以非事务的方式来执行,如果存在事务则抛出一个异常。
23.Spring中Autowired和Resource关键字的区别?
- @Autowired与@Resource都可以用来装配bean.都可以写在字段上,或写在setter方法上。
- @Autowired默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false),如果我们想使用名称装配可以结合@Qualifier注解进行使用。
- @Resource(这个注解属于J2EE的),默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名进行安装名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
以上仅供参考,最好是基于自己的理解来回答面试官,结合自己的项目来讲解,不然很容易被面试官知道是被八股文的。