【八股】Spring 基础知识点

一、Bean 的作用域有哪些?

单例singleton、原型prototype、请求request、会话session、全局会话global-session

需要注意的是,只有作用域为 Singleton 的 Bean 由 Spring IOC容器负责管理和维护,而其他作用域的 Bean 需要在适当的时候手动管理其创建和销毁

二、单例 Bean 的线程安全问题及解决方案?

先了解一下线程安全中有状态、无状态两个概念:1、有状态,就是有数据存储功能并且可读写,线程安全的问题都是由全局变量及静态变量引起的,我们假设每个线程中对全局变量或者静态变量都只可读,那么也就不会存在线程安全问题了;2、无状态,就是不保存数据不存在数据读写问题,当然也就不存在线程安全问题;

解决方案:1、更换 Bean 的作用域为原型模式 @scope("prototype");2、使用 ThreadLocal

三、介绍下 Bean 的生命周期?

实例化、属性赋值、初始化、销毁

整个生命周期相关的方法可以分为三大类:Bean自身的方法、容器级生命周期方法、Bean级生命周期方法;

四、什么是 BeanFactory?和 FactoryBean 的区别?
  • BeanFactory是一个接口,位于类结构树的顶端,定义了getBean()、containsBean()等管理Bean的通用方法,Spring中有很多BeanFactory的实现类,以此来增强BeanFactory的功能;
  • FactoryBean是一个Bean,但不仅仅是一个Bean;它是一个能生产和修饰对象生成的工厂Bean,类似于设计模式中的工厂模式和装饰器模式;它能在需要的时候生产一个对象,返回任何Bean的实例;
五、BeanFactory 和 ApplicationContext 有什么作用?两者之间的区别是什么?
  • ApplicationContext 继承自 BeanFactory ,包含 BeanFactory 的所有功能,面向使用 Spring 框架的开发者,几乎所有的应用场合都可以直接使用 ApplicationContext 而非底层的 BeanFactory;

如果说 BeanFactory 是 Spring 的 “心脏”,那么ApplicationContext就是完整的“身躯”了。ApplicationContext 由 BeanFactory 派生而来,提供了更多面向实际应用的功能。在 BeanFactory 中,很多功能需要以编程的方式实现,而在 ApplicationContext 中则可以通过配置的方式实现

我们一般称 BeanFactory 为 IoC 容器,而称 ApplicationContext 为应用上下文。但有时为了行文方便,我们也将 ApplicationContext 称为 Spring 容器。

六、有几种依赖注入方式?

构造函数注入、setter注入、属性注入

七、注入 Bean 的注解有哪些?@Autowired 和 @Resource 的区别是什么?

Spring 内置的 @Autowired 以及 JDK 内置的 @Resource@Inject 都可以用于注入 Bean。

  • @Autowired 是Spring内置的注解,在注入Bean时,它默认通过byType注入(优先根据接口类型),如果该接口存在多个实现类,则通过byName注入(根据属性名),但是这里需要注意,建议通过 结合@Qualifier 注解来显示指定名称而不是依赖变量的名称。

  • @Resource 时JDK内置的注解,与@Autowired刚好相反,它的默认注入方式是byName,如果无法通过名称匹配到对应的Bean注入方式会变为byType。

@Resource 有两个比较重要且日常开发常用的属性:name(名称)、type(类型)。如果仅指定 name 属性则注入方式为 byName,如果仅指定 type 属性则注入方式为 byType,如果同时指定nametype属性(不建议这么做)则注入方式为 byType + byName

八、@Autowired 底层原理是什么?

@Autowried底层是通过后处理器(AutowiredAnnotationBeanPostProcessor )来实现的,先在IOC容器中找到要注入的对象(先byType再byName),然后通过反射给字段或者方法赋值(就是将找到的Bean实例赋值给字段或者方法);

九、什么是 AOP?AOP 的使用场景?

AOP(面向切面编程)是对面向对象编程的一种补充,AOP能够将那些与业务模块无关,却为业务模块共同调用的责任进行封装,减少重复代码,降低模块间的耦合,增加代码的可扩展性和可维护性。

AOP的实现基于代理,静态代理、JDK动态代理(基于接口类的代理)、CGLIB动态代理,Spring AOP 在运行时通过动态代理技术对要代理的对象(方法)进行增强。

AOP的使用场景:事务管理、缓存管理、日志记录、异常处理、安全控制、性能检测

十、什么情况下 Spring AOP 的动态代理失效?

在 Spring AOP 中,动态代理失效的情况如下:

1、目标类中的方法调用并不是通过 Spring 容器获取的:Spring AOP 的动态代理是基于 Spring 容器的代理机制,只有通过 Spring 容器获取的目标对象才能被代理。如果在目标对象外部直接调用方法,而不是通过 Spring 容器获取目标对象并调用方法,那么动态代理将失效。

2、目标方法是 private、final 的或 static 的:动态代理无法代理目标类中的私有方法、final 方法或静态方法,因为这些方法无法被子类覆盖或继承,无法进行动态代理。

3、目标类没有默认的无参构造方法:动态代理生成代理对象时,需要通过调用目标类的无参构造方法来创建目标对象的实例。如果目标类没有默认的无参构造方法,那么动态代理就无法成功创建代理对象。

十一、AOP 有哪几种通知?执行顺序分别是什么?

前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)环绕通知(Around)

十二、Spring 中事务传播行为有哪些?

事务传播行为是为了解决业务之间互调用的事务问题,当一个事务被另一个事务调用时必须指定事务的传播行为

  • REQURIED:如果当前存在事务就加入,当前不存在事务就新建事务;

  • REQUIRED_NEW:新建事务,如果当前存在事务就将其挂起;

  • NESTED:如果当前存在事务,就新建一个事务作为该事务的嵌套事务;

  • MANDATORY:如果当前存在事务就加入,当前不存在事务就抛出异常;

若是配置以下 3 种事务传播行为,事务将不会发生回滚

  • SUPPORTS:如果当前存在事务就加入,当前不存在事务就以非事务进行执行;
  • NOT_SUPPORTS:以非事务进行执行,如果当前存在事务就将其挂起;
  • NEVER:以非事务进行执行,如果当前存在事务就抛出异常;
十三、Spring事务如何回滚?

当==@Transactional==注解作用在类上时,该类的所有public修饰的方法都具有该类型的事务属性,当然了该注解也可以直接在方法上使用;如果该类中某一个方法抛出了异常,就会回滚,数据库的数据也会回滚;

Spring异常捕获的原理:使用拦截器拦截抛出异常的方法,被AOP代理捕获到方法的异常,然后才进行回滚;

默认Spring事务只发生未捕获的异常时才回滚(RuntimeException、Error),但是也可以通过rollbackFor属性来指定捕获具体的异常然后回滚,亦可通过noRollbackFor属性来执行不捕获某异常;

十四、Spring 事务管理的具体实现方式和底层原理?

Spring 事务管理的核心功能抽象为一个事务管理器(TransactionManager),基于该事务管理器可以有多种事务管理方式(声明式事务、编程式事务);

事务管理器有三大核心功能:获取事务资源、提交事务、回滚事务;

  • 编程式事务(手动):使用TransactionTemplet模版类实现细粒度的事务控制;
  • 声明式事务(自动):基于AOP面向切面编程思想;本质是使用拦截器对目标方法进行拦截,然后执行相应的增强处理,在执行完目标方法之后根据执行情况提交或者回滚事务;声明式事务分为两个部分:一是生成代理增强类;二是根据代理事务管理配置类,配置事务的织入,在业务方法前后进行环绕增强,增加一些事务的相关操作。例如获取事务属性、提交事务、回滚事务。

编程式事务优点是精确控制和动态性,缺点就是代码侵入,增加了代码的复杂性;声明式事务的优点是代码是无侵入的只需添加注解,保证代码简洁,确保一致性和可靠性,缺点就是缺乏灵活性吧,不能根据业务逻辑动态改变事务行为。

十五、Spring 事务失效的情况有哪些?

1、Spring 事务只支持 public 方法,否则不生效

2、方法用 final 修饰,事务不生效

Spring事务底层使用了aop,也就是通过JDK动态代理或者CGLIB生成了代理类,在代理类中实现的事务功能,如果某个方法用final修饰了,那么在它的代理类中无法被重写来添加事务功能;

3、同一个类的内部调用,事务不生效

是因为内部调用绕过了代理对象;

4、未被 Spring 管理的对象使用事务

5、多线程调用

6、数据库引擎不支持事务

十六、什么是 Spring MVC?

MVC是模型、视图、控制器的简写,为了将业务逻辑和视图逻辑进行分离,实现松耦合的架构,提供更好的可扩展性和可测试性;

十七、SpringMVC 工作原理(请求处理流程)是什么?

从接收请求到响应,SpringMVC内部组件紧密配合完成该过程,其中最重要的组件的DispatcherServlet,它负责组织协调其它组件;

1、用户发送请求,匹配相应的DispatcherServlet,匹配成功则将web请求转交给该Servlet;

2、DispatcherServlet根据请求信息(URL、HTTP方法、请求头、请求参数等)以及HandlerMapping的配置信息找到相应的请求处理器(也就是我们写的Controller);

3、处理器处理完结果后,返回一个ModelAndView给DispatcherServlet,DispatcherServlet 借由 ViewResolver完成逻辑视图名到真实视图对象的解析工作;

4、得到真正的视图View对象后,DispatcherServlet用View对象进行渲染ModelAndView;

5、客户端得到的响应消息,可能是一个普通的 HTML 页面,也可能是一个XML或JSON串,甚至是一张图片或一个PDF文档等不同的媒体形式

十八、过滤器和拦截器的区别是什么?

使用范围不同、具体功能不同、触发时机不同、底层实现不同

1、使用范围不同:过滤器实现了java.servlet.Filter接口,该接口在Servlet规范中定义,所以依赖于Tomcat,导致它只能在Web应用程序中使用;拦截器是Spring的一个组件,并由Spring容器管理,不依赖于Tomcat等容器,是可以单独在多种情况下使用的。

2、具体功能不同:过滤器是用于用户请求的预处理;拦截器是对现有方法进行动态增强处理。

3、触发时机不同:过滤器是在用户请求进入容器后,进入Servlet之前触发;拦截器在进入Servlet之后触发。

4、底层实现不同:过滤器是基于回调函数实现的;拦截器是基于动态代理;

十九、SpringBoot启动流程

首先实例化SpringBootApplication,然后调用SpringBootApplication的run方法启动整个SpringBoot程序

1、在实例化SpringBootApplication的过程中会做以下几件事:

  • 检查应用类型是否是Web环境
  • 设置初始化容器(initializer)
  • 设置监听器(Listener)
  • 推断应用入口类Main

2、调用run方法的过程:

  • 获取RunListeners
  • 准备Environment 环境
  • 创建Spring Context
  • Spring Context 前置处理
  • Spring Context 刷新
  • Spring Context 后置处理

@SpringBootApplication注解包含:@SpringBootConfiguration、@ComponentScan、@EnableAutoConfiguration

@SpringBootConfiguration是将当前类标注为Java配置类,并且会被扫描加载到Spring IOC容器中;

@ComponentScan组件扫描,用于将被注解标注的bean扫描加载到容器中;

@EnableAutoConfiguration开启自动装配;

二十、SpringBoot自动装配的原理

首先明白自动装配是什么?—自动装配是SpringBoot根据上下文将Bean装配到IOC容器中;自动装配的核心是扫描约定目录下的文件(META-INFO/spring.factories)进行解析,解析完后把得到的Configuration配置类通过import注册到容器中,从而完成Bean的自动装配过程。

二十一、SpringBoot 有几种方式读取配置文件?

三种方式:@value注解、Environment接口、@ConfigurationProperties注解

一般来说,简单值推荐使用 @Value,复杂对象推荐使用 @ConfigurationProperties

@Value("${com.config.web-configs.name}")
private String name;

@Autowired
Environment environment;
String name = environment.getProperty("com.config.web-configs.name");


//@ConfigurationProperties 可以将配置文件直接映射成一个实体类,然后我们可以直接操作实体类来获取配置文件相关数据。

@Component
@ConfigurationProperties(prefix = "com.config")
@Data
public class StudentProp {
    // webConfigs 务必与配置文件相对应,写为驼峰命名方式
    private WebConfigs webConfigs = new WebConfigs();

    @Data
    public static class WebConfigs {
        private String name;
        private String age;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值