🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:
🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm=1001.2014.3001.5482
🍕 Collection与数据结构 (93平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀线程与网络(96平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
🍬算法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12676091.html?spm=1001.2014.3001.5482
🍃 Spring(97平均质量分)https://blog.csdn.net/2301_80050796/category_12724152.html?spm=1001.2014.3001.5482
🎃Redis(97平均质量分)https://blog.csdn.net/2301_80050796/category_12777129.html?spm=1001.2014.3001.5482
🐰RabbitMQ(97平均质量分) https://blog.csdn.net/2301_80050796/category_12792900.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
目录
- 1. IoC & AOP
- 1.1 IoC是如何实现的
- 1.2 Spring的核心思想
- 1.3 如何在Spring中使用依赖注入
- 1.4 注入的方式有哪些/Spring怎么注入类?
- 1.5 Spring创建的对象是单例的还是多例的,还是原型的?
- 1.6 Spring哪些特性是基于AOP实现的/Spring的AOP在哪用过/Spring AOP的使用场景(*)
- 1.7 SpringBoot中不想加载一个Bean该怎么做?
- 1.8 SpringAOP的机制可以讲一下吗?/SpringAOP基于什么实现?/
- 1.9 多个相同类型的bean,Spring如何判定我们需要的哪一个
- 1.10 Spring中@Resource和@Autowired区别
- 1.11 Spring怎么用到反射的(*)
- 1.12 自己自定义过注解吗,怎么实现的?
- 2. Spring全家桶
- 2.1 Spring和SpringBoot的区别?
- 2.2 Spring,SpringBoot,SpringCloud有什么区别?
- 2.3 你怎么理解Spring全家桶
- 2.4 说说SpringBoot的好处/SpringBoot是什么?
- 2.5 Spring、Springmvc、Springboot是什么?他们仨的区别?
- 2.6 为什么使用SpringCloud,微服务有什么好处/说一下对SpringCloud的理解
- 2.7 SpringCloud用到了哪些组件?
- 3. 事务相关
- 3.1 MySQL的事务和Spring的事务的区别(*)
- 3.2 Spring的事务什么时候失效?(*)
- 3.3 怎么解决Spring事务失效(*)/3.3+3.2=Spring中事务失效的场景有哪些?解决方法?
- 3.4 能不能说说Spring事务/Spring中事务是如何实现的?
- 3.5 介绍一下Spring的事务隔离级别
- 3.6 不加public为何事务失效/Spring中方法是private修饰,事务会生效吗(*)
- 3.7 Spring中事务的传播机制?/Springboot里面的事务传递类型有什么?
- 4. 设计模式
- 4.1 IoC使用了哪些设计模式?
- 4.2 讲讲反射和动态代理,代理模式怎么实现的?
- 4.3 Springboot体现的设计模式说一下/Spring框架使用到的设计模式
- 4.4 Spring的代理机制用过哪些,jdk代理的局限性,代理类的创建过程
- 5. 三级缓存
- 5.1 Spring如何解决循环依赖/Spring3.6以前是如何解决循环依赖问题的
- 5.2 Spring的三级缓存知道吗?
- 5.3 三级缓存为什么要设置第三级(*)
- 6. Bean的生命周期
- 6.1 Spring中一个Bean的生命周期/SpringBean的初始化过程
- 7. 注解相关
- 7.1 Springboot如何接收前端发来的JSON数据
- 7.2 Springboot常用注解
- 7.3 Springboot中如何定义post方法并接收json参数
- 7.4 Springboot中写⼀个http接口的流程
- 7.5 SpringBoot如何读取配置文件的内容
- 8. 其他
- 8.1 Spring的数据库连接池
- 8.2 SpringMVC的执行流程
- 8.3 Springboot中开发环境和测试环境的配置文件是怎么区分的
1. IoC & AOP
1.1 IoC是如何实现的
IoC主要指的是控制权翻转,我们之前需要一个对象的时候,我们需要通过new对象的方式来实现,现在在创建对象的时候,是交给容器来创建的,程序中只需要写一个依赖注入,就可以完成对象的引用.我们首先可以使用例如@Bean
这样的注解来把对象放入IoC容器中,也就是声明Bean对象,之后可以使用@Autowired
注解来完成依赖注入,其中依赖注入(DI)就是IoC的核心思想,依赖注入主要有三种方式,属性注入,就是在类的属性上直接加上@Autowired
注解直接进行注入,另一种就是构造方法注入,其中构造方法的参数中应该包含所要注入的属性,之后在构造方法上加上Autowired
注解.最后一种是通过Setter注入,和构造方法同理.
1.2 Spring的核心思想
Spring的两大核心思想是IoC和AOP,其中IoC指的是控制权翻转,我们之前想要得到一个对象的时候,我们需要通过new对象的方式来实现,现在在创建对象的时候,是交给容器来创建的,也就是对象的控制权在Spring IoC容器手上.
AOP指的是面相切面编程,切面就指的是某一类特定的问题,所以面向切面编程就是针对同一类问题来进行编程,简单来说就是针对与统一类问题的集中解决.其中Spring AOP是AOP的一种实现方式.
1.3 如何在Spring中使用依赖注入
可以使用@Autowired
注解来完成依赖注入,依赖注入主要有三种方式,属性注入,就是在类的属性上直接加上@Autowired
注解直接进行注入,另一种就是构造方法注入,其中构造方法的参数中应该包含所要注入的属性,之后在构造方法上加上Autowired
注解.最后一种是通过Setter注入,和构造方法同理.但是这个注解在一些场景之下会存在一定的问题.由于Autowired
是按照类名进行注入的,也就是容器中如果含有两个类型相同的对象,使用这个注解便不可完成注入.我们可以使用Resource
注解直接根据对象名注入,也可以使用Qualifier
注解和Autowired
搭配使用,在Qualifier
后面指定要注入的Bean的名称.
1.4 注入的方式有哪些/Spring怎么注入类?
首先是使用Autowired
注入,依赖注入主要有三种方式,属性注入,就是在类的属性上直接加上@Autowired
注解直接进行注入,另一种就是构造方法注入,其中构造方法的参数中应该包含所要注入的属性,之后在构造方法上加上Autowired
注解.最后一种是通过Setter注入,和构造方法同理.
由于Autowired
是按照类名进行注入的,也就是容器中如果含有两个类型相同的对象,使用这个注解便不可完成注入.我们可以使用Resource
注解直接根据对象名注入,也可以使用Qualifier
注解和Autowired
搭配使用,在Qualifier
后面指定要注入的Bean的名称.也可以把Primary
注解加载对应的Bean上面,如果一个类的Bean有多个,默认注入的是加上Primary
的这个Bean.
1.5 Spring创建的对象是单例的还是多例的,还是原型的?
Spring在IoC容器中创建的对象叫做Bean,Bean的作用域默认是单例的,但是我们可以通过@Scope
注解来改变Bean的作用域,如果想要使得Bean变为原型的,也就是多例的,需要在@Scope
注解后面加上ConfigurableBeanFactory.SCOPE_PROTOTYPE
来让Bean编程多例的,加上这个注解可以让Bean在每次被使用的时候都要重新创建.此外还有其他的作用域可供选择,比如加上@RequestScope
就是每次请求都会创建一个新的Bean,@SessionScope
就是每个会话周期都会创建一个Bean等.
1.6 Spring哪些特性是基于AOP实现的/Spring的AOP在哪用过/Spring AOP的使用场景(*)
- Spring的声明式事务也是通过AOP实现的.声明式事务通过添加
Transactional
注解即可实现,如果在事务的中途出现了异常,事务会自动回滚掉. - Spring的日志记录是通过AOP实现的.可以在方法执行前后打印一些日志,方便观察程序执行的过程和后期进行调试.
- Spring的性能监控是通过AOP实现的,可以在方法执行前后加上时间戳,最后通过作差来判断一个接口的性能.
- Spring的权限验证是通过AOP实现的,可以在方法执行之间判断一个用户是否有访问这个接口的权限,如果没有,需要即使阻止.
1.7 SpringBoot中不想加载一个Bean该怎么做?
我们可以在Spring的启动类上使用@ComponentScan
手动配置Bean的扫描路径,可以把一个Bean配置到没有被扫描的路径下,即可让一个Bean不被加载.也可以为该注解中的excludeFilters
属性指定一个过滤器,把不需要加载的Bean直接过滤掉.
@SpringBootApplication
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = MyBean.class))
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}
1.8 SpringAOP的机制可以讲一下吗?/SpringAOP基于什么实现?/
SpringAOP主要是通过代理模式来实现的,代理模式就是我们在调用方法的时候,我们不是直接调用该方法,而是通过代理类来间接调用,代理模式分为静态代理模式和动态代理模式,其中SpringAOP主要是通过动态代理模式来实现的,其中使用到的动态代理又分为JDK动态代理和CGLIB动态代理,其中JDK的动态代理只可以代理实现接口的类,JDK的动态代理类通过实现InvocationHandler
接口并重写invoke
方法来定义代理类,而CGLIB动态代理即可以代理实现接口的类,也可以代理没有实现接口的类,CGLIB动态代理通过实现MethodInterceptor
接口来实现代理类,并重写intercept
方法.
1.9 多个相同类型的bean,Spring如何判定我们需要的哪一个
如果相同类型的Bean有多个,我们可以使用@Resource
根据属性的名字来进行注入,需要Bean的名字和属性的一致便可注入.也可以使用Qualifier
注解和Autowired
搭配使用,在Qualifier
后面指定要注入的Bean的名称便可以完成注入.也可以把Primary
注解加载对应的Bean上面,如果一个类的Bean有多个,默认注入的是加上Primary
的这个Bean.
1.10 Spring中@Resource和@Autowired区别
@Autowired是spring框架提供的注解,而@Resource是JDK提供的注解
@Autowired默认是按照类型注入,而@Resource是按照名称注入.相比于@Autowired来说,@Resource支持更多的参数设置,例如name设置,根据名称获取Bean。
一般情况下,一个类有多个对象的时候我们习惯用@Resource,是单例的时候,我们习惯用@Autowired
1.11 Spring怎么用到反射的(*)
- Bean的创建和依赖注入:Spring 容器通过反射机制创建Bean实例,并将依赖注入到对应的属性中.
- AOP:AOP的代理模式中通过反射动态调用被代理的方法(invoke方法的执行).
- 注解解析: Spring 使用反射机制解析类、方法或字段上的注解,并根据注解配置执行相应的逻辑.
- Bean的初始化和销毁: Spring使用反射机制调用Bean的初始化方法和销毁方法.
1.12 自己自定义过注解吗,怎么实现的?
想要定义一个注解,首先需要使用到元注解来对这个注解进行修饰,第一个是Target
注解,表示的是这个注解可以加在什么地方,可以设置加在类上,加在方法上,加在参数前,也可以添加在任何位置.之后需要Retention
注解来定义注解的生命周期,可以让注解只在存在于源码阶段,可以存在于字节码阶段和源码阶段,也可以存在于运行阶段,字节码阶段,和源码阶段.之后就可以在注解体中添加属性,使用default关键字指定默认值.
SpringAOP在使用@annotation
创建切点表达式的时候,在annotation
指定我们的自定义注解之后,凡是加上自定义注解的方法都要被这个切面进行统一处理.
2. Spring全家桶
2.1 Spring和SpringBoot的区别?
Spring是一个功能强大的企业级开发框架,旨在解决企业级应用开发的复杂性问题,提高开发效率和代码的可维护性,包含了丰富而全面的基础设施,比如依赖注入,事务管理等.而SpringBoot旨在简化Spring框架的初始搭建和开发过程,SpringBoot就是Spring的脚手架,采用了约定优于配置的原则,提供了大量的默认配置和 Starter 依赖,目标是提供开箱即用的配置,快速构建应用程序,减少了开发者大量手动配置的操作.
2.2 Spring,SpringBoot,SpringCloud有什么区别?
Spring是一个功能强大的企业级开发框架,旨在解决企业级应用开发的复杂性问题,提高开发效率和代码的可维护性,包含了丰富而全面的基础设施,比如依赖注入,事务管理等.而SpringBoot旨在简化Spring框架的初始搭建和开发过程,SpringBoot就是Spring的脚手架,采用了约定优于配置的原则,提供了大量的默认配置和 Starter 依赖,目标是提供开箱即用的配置,快速构建应用程序,减少了开发者大量手动配置的操作.SpringCloud是基于SpringBoot构建的一套微服务开发框架,帮助开发者快速构建分布式系统的相关组件和配置,比如网关,服务注册,服务发现等.是分布式微服务架构的一站式解决方案.
2.3 你怎么理解Spring全家桶
Spring全家桶是一系列相互协作、功能丰富的Spring相关框架和工具的集合,为Java企业级开发提供了一站式解决方案,能够满足从单体应用到分布式微服务架构等各种不同规模和复杂度项目的开发需求.其中主要的内容包含SpringFramework,SpringBoot,SpringCloud,SpringData等.
2.4 说说SpringBoot的好处/SpringBoot是什么?
SpringBoot基于Spring框架,旨在简化Spring框架的初始化搭建以及开发过程.SpringBoot就是Spring的脚手架,采用了约定优于配置的原则,提供了大量的默认配置和 Starter 依赖,目标是提供开箱即用的配置,快速构建应用程序,减少了开发者大量手动配置的操作.
2.5 Spring、Springmvc、Springboot是什么?他们仨的区别?
Spring是一个功能强大的企业级开发框架,旨在解决企业级应用开发的复杂性问题,提高开发效率和代码的可维护性,包含了丰富而全面的基础设施,比如依赖注入,事务管理等.
而SpringBoot旨在简化Spring框架的初始搭建和开发过程,SpringBoot就是Spring的脚手架,采用了约定优于配置的原则,提供了大量的默认配置和 Starter 依赖,目标是提供开箱即用的配置,快速构建应用程序,减少了开发者大量手动配置的操作.
MVC是Model View Controller的缩写,是软件工程中的一种软件架构的设计模式.把软件系统分为模型,控制器,视图三个部分,而Spring MVC是一个实现了MVC软件设计模式的Web框架.我们在初始化SpringBoot框架的时候,一开始要引入SpringWeb依赖就是引入了SpringMVC的软件设计模式.
2.6 为什么使用SpringCloud,微服务有什么好处/说一下对SpringCloud的理解
SpringCloud是针对与分布式微服务架构的一站式解决方案,可以帮助开发者快速构建微服务架构中的各种组件,SpringCloud基于SpringBoot的风格,对这些微服务架构组件进行了封装,屏蔽了复杂的配置与原理实现,给开发者提供一种开箱即用的开发体验.
- 微服务中每个服务相互隔离,一个服务出现故障,不会影响其他服务的正常运行.
- 每个微服务负责的业务比较清晰,体量较小,开发和维护成本较低.
- 每个服务都是独立运行的,可以结合项目的实际情况进行扩展,按需求伸缩.
- 每个服务都是由单独的团队独立开发和为何,可以根据该服务的特点和团队的特点,灵活选择技术选型和技术栈.
2.7 SpringCloud用到了哪些组件?
SpringCloud的常用组件有:
- Eureka:是SpringCloud服务注册与发现的默认实现,主要分为Server和Client两部分,Server向应用程序提供服务注册,发现,健康检查的能力.Client负责向Server注册自己的信息,Server会存储这些信息.
- SpringCloudLoadBalancer: SpringCloud官方的开发的负载均衡组件.当服务流量增大时,负载均衡会在多态服务器之间合理分配负载.
- Nacos:Nacos是阿里巴巴开源的一款服务发现与注册,配置管理的组件,功能和Eureka类似,但是由比Eureka强大.
- OpenFeign: 可以简化微服务之间的调用,可以让微服务之间的调用像IoC那样简单.
- Gateway: 在访问各个服务之前,需要网关首先对用户的权限进行校验,是后端服务的唯一入口.
3. 事务相关
3.1 MySQL的事务和Spring的事务的区别(*)
- 概念层面
MySQL的事务是针对是数据库层面的事务,对表的修改要不都成功,要不都失败,以此来保证数据的完整性和一致性.Spring的事务是应用层面的事务,是基于SpringAOP原理实现的,将数据库层面的事务进行了抽象和封装,让开发者不必要关心数据库底层的一些细节. - 应用层面
MySQL的事务一般用于数据库增删查改的操作的时候保证数据的一致性.Spring的事务一般用于应用程序的业务逻辑层,一般这个业务逻辑会涉及到多个模块的业务逻辑或者是不止一张表的增删查改. - 使用方式
MySQL使用start transaction
开启事务,使用commit
提交事务,而Spring的事务一般使用@Transactional
注解来标注需要开启事务的方法. - 事务的传播行为
在MySQL中没有事务的传播,而在Spring中的事务中,如果一个方法中调用了其他的方法,事务会在这几个方法中按照一定的规则进行传播.
3.2 Spring的事务什么时候失效?(*)
- 方法是private修饰的事务会失效: Spring的事务是基于AOP实现的,而AOP代理对象需要被代理的方法是public修饰的,否则无法进行代理.
- Transactional默认只对RuntimeException和Error进行回滚,如果是其他类型的异常,默认不会回滚,需要使用rollbackFor属性指定需要回滚的异常类型.
- 如果带有事务的方法在当前类中的方法中被调用,则事务不会生效,这是由于这种调用方法不会经过代理对象,而是直接调用了目标方法.
- 可能是当前数据库不支持事务.
- 多线程环境之下可能引起,如果在一个事务方法中新开启了一个线程去执行修改数据库的操作,事务会失效,这是由于每个线程的上下文都是独立的.
3.3 怎么解决Spring事务失效(*)/3.3+3.2=Spring中事务失效的场景有哪些?解决方法?
- 首先针对private修饰的方法,事务会失效的问题,可以把方法的修饰改为public.
- 针对异常类型不匹配产生的事务失效,可以使用rollbackFor属性来指定需要回滚的异常.
- 针对同一类中的方法调用带有事务的方法,可以把被调用的这个方法添加到其他的类,以免AOP中的代理对象被绕过.
- 针对多线程产生的事务失效,可以尽量避免使用多线程的使用,如果确实需要,可以使用分布式事务来解决.
- 针对数据库不支持事务,可以使用支持事务的存储引擎,比如MySQL的Innodb引擎.
3.4 能不能说说Spring事务/Spring中事务是如何实现的?
Spring的事务分为两种,一种是编程式事务,一种是声明式事务,编程式事务就是手动完成事务的开启与提交,我们可以通过DataSourceTransactionManager
来实现对事务的开启,提交,以及回滚,声明式事务是通过给方法加上Transactional
注解来实现,可以在注解后面使用rollbackFor
属性指定出现指定异常的时候回滚,使用lsolation
指定事务的隔离级别,通过Propagation
属性来指定事务在方法之间的传播行为.
3.5 介绍一下Spring的事务隔离级别
Spring的事务隔离级别一共有5中,第一种是Default,就是按照数据库的事务隔离级别来走,第二种是Read_Uncommitted读未提交,会产生脏读问题,第三种是Read_commited读提交,可能会产生不可重复读问题,第四种是Repeatable_Read可重复读,可能会产生幻读问题,最后一种是SERIALIZABLE串行化.事务的隔离级别通过Transactional注解的Isolation来控制.
3.6 不加public为何事务失效/Spring中方法是private修饰,事务会生效吗(*)
(private修饰的方法事务不会生效)这是由于事务是基于AOP原理实现的,而AOP又是代理模式实现的,代理模式分为JDK动态代理和CGLIB动态代理,JDK无法实现对private方法的代理是因为JDK只能代理实现接口的类,而接口中的方法默认是public的,如果是private的,则无法对其进行增强.其次是CGLIB动态代理,和Java的字节码处理规则有关系,CGLIB无法对private的方法进行重写.所以代理对象的修饰必须是public的,否则无法进行代理.
3.7 Spring中事务的传播机制?/Springboot里面的事务传递类型有什么?
事务传播机制指的是多个事务方法在相互调用的时候,事务是如何在方法之间进行传播的,事务传递的行为通常使用Propagation属性来指定,常见的事务传递行为的类型有:
- Propagation.REQUIRED:加入事务,默认的事务传播级别.如果当前(表示在一个方法中被调用的方法)存在事务,则加入该事务,如果当前没有事务,则创建一个新的事务.(加入事务,就是共用一个事务,一个事务发生异常,全部回滚.)
- Propagation.SUPPORTS:如果当前存在事务,则加入该事务.如果当前没有事务,则以非事务的方式继续运行.
- Propagation.MANDATORY:强制性,如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常.
- Propagation.REQUIERS_NEW:新建事务,创建一个新事务如果当前存在事务,则把当前事务挂起.(发生异常,不影响其他事务)也就是不管外部方法是否开启事务,Propagation.REQUIERS_NEW修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干涉.
- Propagation.NOT_SUPPORTED: 以非事务的方式运行,如果当前存在事务则把当前事务挂起.
- Propagation.NEVER: 不支持当前事务,以非事务的方式运行,如果存在事务,则抛出异常.
- Propagation.NESTED: 嵌套事务,如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行,如果当前没有事务,则该取值等价于Propagation.REQUIRED.
1,4对应,2,5对应,3,6对应.
4. 设计模式
4.1 IoC使用了哪些设计模式?
- 工厂模式: SpringIoC容器本身就是一个工厂,负责创建和管理Bean.
AppliactionContext
是工厂提供的一个接口,即上下文,可以从该接口中对Bean进行一系列的操作,一般在启动类中进行使用. - 单例模式: 在向容器中加入一个Bean的时候,默认加入的Bean就是单例的,如果想要改变,可以使用
@Scope
注解来改变. - 原型模式: 如果使用
@Scope
注解指定注入的bean是prototype的,bean就是原型的,即每次调用都会重新创建一个Bean. - 依赖注入模式: SpringIoC的核心就是依赖注入,注入可以通过构造方法,Setter方法,或者是属性注入.一般使用
@Autowired
进行注入.
4.2 讲讲反射和动态代理,代理模式怎么实现的?
反射和动态代理主要是SpringAOP的实现原理,使用代理模式之后就不是直接访问到目标方法,而是通过代理模式在间接访问,SpringAOP的动态代理模式分为JDK动态代理和CGLIB动态代理,JDK动态代理只可以代理实现接口的类,而CGLIB动态代理既可以实现没有实现接口的类,也可以实现实现接口的类.两个动态代理的invoke
方法通过反射拿到被代理的对象并调用目标方法.
4.3 Springboot体现的设计模式说一下/Spring框架使用到的设计模式
IoC:
- 工厂模式: SpringIoC容器本身就是一个工厂,负责创建和管理Bean.
AppliactionContext
是工厂提供的一个接口,即上下文,可以从该接口中对Bean进行一系列的操作,一般在启动类中进行使用. - 单例模式: 在向容器中加入一个Bean的时候,默认加入的Bean就是单例的,如果想要改变,可以使用
@Scope
注解来改变. - 原型模式: 如果使用
@Scope
注解指定注入的bean是prototype的,bean就是原型的,即每次调用都会重新创建一个Bean. - 依赖注入模式: SpringIoC的核心就是依赖注入,注入可以通过构造方法,Setter方法,或者是属性注入.一般使用
@Autowired
进行注入.
日志: - 门面模式: 日志框架包含很多种类,如果多套日志框架共存,在调用的时候不得不调用不同日志框架的API,非常的不方便,这时候Slf4j就对这些日志框架进行了统一,之后使用一套统一的API接口提供给用户.
拦截器: - Spring的拦截器通过
HandlerExecutionChain
将HandlerInterceptor
适配到SpringMVC中的处理流程中.最终使得拦截器和SpringMVC完成解耦.
AOP: - 代理模式: AOP的实现原理使用的是代理模式,代理模式使用的是动态代理的模式,分为JDK动态代理和CGLIB动态代理.
4.4 Spring的代理机制用过哪些,jdk代理的局限性,代理类的创建过程
SpringAOP主要是通过代理模式来实现的,代理模式就是我们在调用方法的时候,我们不是直接调用该方法,而是通过代理类来间接调用,代理模式分为静态代理模式和动态代理模式,其中SpringAOP主要是通过动态代理模式来实现的,其中使用到的动态代理又分为JDK动态代理和CGLIB动态代理,其中JDK的动态代理只可以代理实现接口的类,JDK的动态代理类通过实现InvocationHandler
接口并重写invoke
方法来定义代理类,在构造方法中传入需要被代理的对象Object,而CGLIB动态代理即可以代理实现接口的类,也可以代理没有实现接口的类,CGLIB动态代理通过实现MethodInterceptor
接口来实现代理类,并重写intercept
方法,在构造方法中传入需要被代理的对象Object.
5. 三级缓存
5.1 Spring如何解决循环依赖/Spring3.6以前是如何解决循环依赖问题的
Spring使用了三级缓存来解决循环依赖.比如A对象和B对象相互依赖.
- A的工厂对象被初始化,放入了三级缓存.
- 在A对象为他的其中的B赋值的时候,发现B对象并没有创建.
- B的工厂对象被创建,放入三级缓存中.
- 从三级缓存中获取A对象的工厂,从而创建A对象的半成品,此时A对象还是不完整的Bean,A被放入二级缓存中.
- 在二级缓存中找到了A对象,为B对象的A属性赋值.
- B对象进行后续的处理,注入其他的依赖,初始化,之后B对象就是一个完整的Bean了,就会被放入一级缓存.
- A对象进行后续的处理,注入其他的依赖,初始化,之后A对象也是一个完整的Bean了,就会被放入一级缓存.
5.2 Spring的三级缓存知道吗?
Spring的三级缓存是用来解决循环依赖的问题的,三级缓存中,三级缓存存放的是Bean的工厂,工厂用来创造提前暴露的Bean,二级缓存是用来存放提前暴露的Bean,即不完整的Bean,一级缓存用来存储完全初始化好的Bean,即完整的Bean.
5.3 三级缓存为什么要设置第三级(*)
- 延迟生成早期的引用: 只有在真正需要这个Bean的时候才会生成这个Bean的早期引用放入到二级缓存中,避免不必要的开销.
- 支持Bean的后置处理: 如果这个Bean存在代理对象,可以通过三级缓存生成他的代理,之后使用到的时候,在二级缓存中存储的就是他的代理对象.
6. Bean的生命周期
6.1 Spring中一个Bean的生命周期/SpringBean的初始化过程
Bean的生命周期一共分为5个部分:
- 实例化Bean,为Bean分配内存空间.
- 赋值Bean属性,使用
@Autowired
为Bean的属性赋值. - 初始化Bean,执行各种通知,比如
BeanNameAware
中的setBeanName
方法,通知Bean在容器中的名字,BeanFactoryAware
中的setBeanFactory
方法创建该Bean的工厂.ApplicationContextAware
中的setBeanApplicationContext
方法传递该Bean的上下文.执行使用PostConstruct
注解修饰的自定义初始化方法,之后看Bean是否实现了InitializingBean
的接口,如果实现了,就调用其中的afterPropertiesSet
方法来执行属性赋值之后的一些初始化. - 使用Bean
- 销毁Bean,执行销毁容器的各种方法.首先执行
@PreDistroy
修饰的自定义销毁方法,之后看Bean是否实现DisposableBean
接口,如果实现了,就执行其中的destroy
方法,执行销毁时的清理操作.
7. 注解相关
7.1 Springboot如何接收前端发来的JSON数据
为参数加上@RequestBody
注解.
7.2 Springboot常用注解
@RestController
,@Controller
,@Service
,@Mapper
,@Component
,@Configuration
,@RequestMapping
,@SpringBootAppliation
,@Autowired
,@Test
,@Resource
,@Bean
,@Slf4j
,@Value
,@ResponseBody
,ControllerAdvice
,@ExceptionHandler
,@Around
,@Before
,@After
,@Pointcut
(用来提取公共切点表达式),@Order
指定切面优先级.
7.3 Springboot中如何定义post方法并接收json参数
使用@PostMapping
注解规定该方法只能接受Post请求,为参数加上@RequestBody
注解来接收Json参数.
7.4 Springboot中写⼀个http接口的流程
使用@RequestMapping
注解给一个方法指定HTTP路由,之后再方法中写入该接口需要执行的业务逻辑,之后使用返回值的形式把返回值返回给前端.
7.5 SpringBoot如何读取配置文件的内容
使用@Value
注解,后面的参数使用${}
把配置文件中的内容路径写出来.
8. 其他
8.1 Spring的数据库连接池
数据库连接池技术也是一种池化技术,他与线程池类似,在通过Spring连接数据库的时候,避免了频繁的创建和销毁与数据库的连接.保证了资源的合理利用.在程序启动之后,会在连接池内创建一个Collection对象,之后在执行SQL的时候,就会在连接池内申请一个连接对象,在执行完SQL之后就会把连接对象归还给线程池.
8.2 SpringMVC的执行流程
- 首先浏览器给Controller发送一个网络请求.
- 后端选择合适的模型进行处理,并把结果返回给Controller.
- Controller选择合适的视图,把视图返回给浏览器.
8.3 Springboot中开发环境和测试环境的配置文件是怎么区分的
我们可以使用SpringBoot配置文件中的Profile
机制.Profile
是一种隔离配置的方式,允许你为不同的环境定义不同的配置,并在运行时动态切换.我们可以在一个项目中创建两个配置文件,一个是application-dev.yml,一个是application-test.yml,第一个文件中是开发环境的配置,第二个文件值测试环境的配置,之后再application.yml文件中使用spring.profile.active
属性指定当前的环境.