Spring 

 1.1 什么是Spring IOC 和DI ? 

 ① 控制反转(IOC):Spring容器使用了工厂模式为我们创建了所需要的对象,我
们使用时不需要自己去创建,直接调用Spring为我们提供的对象即可,这就是控
制反转的思想。
② 依赖注入(DI):Spring使用Java Bean对象的Set方法或者带参数的构造方法为
我们在创建所需对象时将其属性自动设置所需要的值的过程就是依赖注入的基本
思想。 

 1.2 有哪些不同类型的依赖注入实现方式?
 依赖注入分为Setter方 法注入和构造器注入
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类
有一系列参数,每 个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方
法实例化bean之 后,调用该bean的setter方法,即实现了基于setter的依赖注
入。 

 1.3 Spring支持的几种bean的作用域 

 Spring框架支持以下五种bean的作用域:


singleton : bean在每个Spring ioc 容器中只有一个实例。


prototype:一个bean的定义可以有多个实例。


request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring
ApplicationContext情形下有效。


session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的 Spring ApplicationContext情形下有效。


application:属于应用程序域,应用程序启动时bean创建,应用程序销毁时bean销毁。该作用域仅在基于web的ServletContext. 

 1.4 Spring框架中的单例bean是线程安全的吗? 

 不是线程安全的


当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线
程会并发执行该请求对应的业务逻辑(成员方法),如果该处理逻辑中有对该单
列状态的修改(体现为该单例的成员属性),则必须考虑线程同步问题。


Spring框架并没有对单例bean进行任何多线程的封装处理。关于单例bean的线程
安全和并发问题需要开发者自行去搞定。


Spring bean并没有可变的状态(比如Service类和DAO类),所以在某种程度上说
Spring的单例bean是线程安全的。


如果你的bean有多种状态的话(比如 View Model对象),就需要自行保证线程
安全。最浅显的解决办法就是将多态bean的作用由“singleton”变更为
“prototype”。 

 1.5 Spring自动装配 bean 有哪些方式? 

 spring的自动装配功能的定义:无须在Spring配置文件中描述javaBean之间的依
赖关系(如配置 <property>、<constructor-arg> )。
自动装配模式:
1、no:这是 Spring 框架的默认设置,在该设置下自动装配是关闭的,开发者需
要自行在 bean 定义中用标签明确的设置依赖关系 。


2、byName:该选项可以根据bean名称设置依赖关系 。 当向一个bean中自动装
配一个属性时,容器将根据bean的名称自动在在配置文件中查询一个匹配的
bean。 如果找到的话,就装配这个属性,如果没找到的话就报错 。


3、byType:该选项可以根据 bean 类型设置依赖关系 。 当向一个 bean 中自动
装配一个属性时,容器将根据 bean 的类型自动在在配置文件中查询一个匹配的
bean。 如果找到的话,就装配这个属性,如果没找到的话就报错 。


4、constructor :构造器的自动装配和byType模式类似,但是仅仅适用于与有构
造器相同参数的bean,如果在容器中没有找到与构造器参数类型一致的bean ,
那么将会抛出异常 。


5、default:该模式自动探测使用构造器自动装配或者byType自动装配 。 首先会
尝试找合适的带参数的构造器,如果找到的话就是用构造器自动装配,如果在
bean内部没有找到相应的 构造器或者是无参构造器,容器就会自动选择 byTpe
的自动装配方式 。 

 比如如下注入 :

 可以改造为: 

 1.6 你用过哪些重要的Spring注解? 

 1、@Component- 用于服务类 

@Service
@Repository
@Controller

 2、@Autowired - 用于在 spring bean 中自动装配依赖项。通过类型来实现自动
注入bean。和@Qualifier注解配合使用可以实现根据name注入bean。


3、@Qualifier - 和@Autowired一块使用,在同一类型的bean有多个的情况下可
以实现根据name注入的需求。


4、@Scope - 用于配置 spring bean 的范围。


5、@Configuration,@ComponentScan 和 @Bean - 用于基于 java 的配置。


6、@Aspect,@Before,@After,@Around,@Pointcut - 用于切面编程(AOP) 

 1.7 Spring中的事务是如何实现的

 Spring支持编程式事务管理和声明式事务管理两种方式!
编程式事务控制:需要使用TransactionTemplate来进行实现,这种方式实现对业
务代码有侵入性,因此在项目中很少被使用到。


声明式事务管理:声明式事务管理建立在AOP之上的。其本质是通过AOP功能,
对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在
目标方法开始之前加入一个事务,在执行完目标方法之后根据执行情况提交或者
回滚事务。


声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码,只需
在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可
以将事务规则应用到业务逻辑中。 

 1.8 Spring中事务失效的场景? 

 因为Spring事务是基于代理来实现的,所以某个加了@Transactional的⽅法只有
是被代理对象调⽤时, 那么这个注解才会⽣效 , 如果使用的是目标对象调用, 那
么@Transactional会失效


同时如果某个⽅法是private的,那么@Transactional也会失效,因为底层cglib是
基于⽗⼦类来实现 的,⼦类是不能重载⽗类的private⽅法的,所以⽆法很好的
利⽤代理,也会导致@Transactianal失效


如果在业务中对异常进行了捕获处理 , 出现异常后Spring框架无法感知到异常,
@Transactional也会失效


@Transactional中的配置的Rollback的默认是异常是:runTimeException,更改为

Spring的事务传播行为 Exception 

 1. PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当
前存在事务,就 加入该事务,该设置是最常用的设置。


2. PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事
务,如果当前不 存在事务,就以非事务执行。


3. PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该
事务,如果当前 不存在事务,就抛出异常。


4. PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创
建新事务。


5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事
务,就把当前 事务挂起。


6. PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异
常。


7. PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当
前没有事务,则 按REQUIRED属性执行 

 1.10 什么是AOP , 你们项目中有没有使用到AOP 

 AOP一般称为面向切面编程,作为面向对象的一种补充,用于 将那些与业务无
关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模
块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块
间的耦合度,同时 提高了系统的可维护性。
在我们的项目中我们自己写AOP的场景其实很少 , 但是我们使用的很多框架的功
能底层都是AOP , 例如 :
1、统一日志处理
2、spring中内置的事务处理 

记录操作日志
需求:是谁,在什么时间,修改了数据(修改之前和修改之后),删除了什
么数据,新增了什么数据
要求:方法命名要规范
实现步骤:
1,定义切面类
2,使用环绕通知,根据方法名和参数,记录到表中

1.11 JDK动态代理和CGLIB动态代理的区别

Spring中AOP底层的实现是基于动态代理进行实现的。
常见的动态代理技术有两种:JDK的动态代理和CGLIB。
两者的区别如下所示:
1、JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2、Cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
进行增强,但是因为采用的是继承,所以该类或方法最好不要声明为final,对于
final类或方法,是无法继承的。
Spring如何选择是用JDK还是cglib?
1、当bean实现接口时,会用JDK代理模式
2、当bean没有实现接口,会用cglib实现
3、可以强制使用cglib

在springboot项目可以配置以下注解,强制使用cglib

@EnableAspectJAutoProxy(proxyTargetClass = true)
 

spring的bean的生命周期

bean 的生命周期从调用 beanFactory 的 getBean 开始,到这个 bean 被销毁,可
以总结为以下七个阶段:
1. 处理名称,检查缓存
2. 处理父子容器
3. 处理 dependsOn
4. 选择 scope 策略
5. 创建 bean (关键阶段)
6. 类型转换处理
7. 销毁 bean

spring框架在创建的bean的时候都会调用AbstractBeanFactory类中的doGetBean
方法

1. 处理名称,检查缓存
  这一步会处理别名,将别名解析为实际名称

对 FactoryBean 也会特殊处理,如果以 & 开头表示要获取 FactoryBean 本身,否则表示要获取其产品

这里针对单例对象会检查一级、二级、三级缓存
  singletonFactories 三级缓存,存放单例工厂对象
  earlySingletonObjects 二级缓存,存放单例工厂的产品对象
    如果发生循环依赖,产品是代理;无循环依赖,产品是原始对象
  singletonObjects 一级缓存,存放单例成品对象
  2. 处理父子容器
  如果当前容器根据名字找不到这个 bean,此时若父容器存在,则执行父容器的 getBean 流程
  
  父子容器的 bean 名称可以重复

3. 处理 dependsOn
    如果当前 bean 有通过 dependsOn 指定了非显式依赖的 bean,这一步会提前创建这些 dependsOn 的 bean
    
    所谓非显式依赖,就是指两个 bean 之间不存在直接依赖关系,但需要控制它们的创建先后顺序

4. 选择 scope 策略
  对于 singleton scope,首先到单例池去获取 bean,如果有则直接返回,没有再进入创建流程

  对于 prototype scope,每次都会进入创建流程

  对于自定义 scope,例如 request,首先到 request 域获取 bean,如果有则直接返回,没有再进入创建流程 
   

 5.1 创建 bean - 创建 bean 实例 

要点 总结
AutowiredAnnotationB
eanPostProcessor
① 优先选择带 @Autowired 注解的构造;② 若有
唯一的带参构造,也会入选
采用默认构造 如果上面的后处理器和 BeanDefiniation 都没找到构
造,采用默认构造,即使是私有的

 5.2 创建 bean - 依赖注入 

要点 总结
AutowiredAnnotation
BeanPostProcessor
识别 @Autowired 及 @Value 标注的成员,封装为
InjectionMetadata 进行依赖注入
CommonAnnotationBe
anPostProcessor
识别 @Resource 标注的成员,封装为
InjectionMetadata 进行依赖注入
AUTOWIRE_BY_NAME 根据成员名字找 bean 对象,修改 mbd 的
propertyValues,不会考虑简单类型的成员
AUTOWIRE_BY_TYPE 根据成员类型执行 resolveDependency 找到依赖注入
的值,修改 mbd 的 propertyValues
要点 总结
applyPropertyValues 根据 mbd 的 propertyValues 进行依赖注入(即xml中
<property name ref|value/>)

 5.3 创建 bean - 初始化 

要点 总结
内置 Aware
接口的装配
包括 BeanNameAware,BeanFactoryAware 等
扩展 Aware
接口的装配
由 ApplicationContextAwareProcessor 解析,执行时机在
postProcessBeforeInitialization
@PostConstr
uct
由 CommonAnnotationBeanPostProcessor 解析,执行时机在
postProcessBeforeInitialization
InitializingBe
an
通过接口回调执行初始化
initMethod 根据 BeanDefinition 得到的初始化方法执行初始化,即
<bean init-method> 或 @Bean(initMethod)
创建 aop 代
由 AnnotationAwareAspectJAutoProxyCreator 创建,执行时机
在 postProcessAfterInitialization

 5.4 创建 bean - 注册可销毁 bean

 在这一步判断并登记可销毁 bean
判断依据
如果实现了 DisposableBean 或 AutoCloseable 接口,则为可销毁 bean
如果自定义了 destroyMethod,则为可销毁 bean
如果采用 @Bean 没有指定 destroyMethod,则采用自动推断方式获取销毁
方法名(close,shutdown)
如果有 @PreDestroy 标注的方法
存储位置
singleton scope 的可销毁 bean 会存储于 beanFactory 的成员当中
自定义 scope 的可销毁 bean 会存储于对应的域对象当中
prototype scope 不会存储,需要自己找到此对象销毁
存储时都会封装为 DisposableBeanAdapter 类型对销毁方法的调用进行适配
6. 类型转换处理
如果 getBean 的 requiredType 参数与实际得到的对象类型不同,会尝试进行
类型转换
7. 销毁 bean
销毁时机
singleton bean 的销毁在 ApplicationContext.close 时,此时会找到所有
DisposableBean 的名字,逐一销毁
自定义 scope bean 的销毁在作用域对象生命周期结束时
prototype bean 的销毁可以通过自己手动调用
AutowireCapableBeanFactory.destroyBean 方法执行销毁
同一 bean 中不同形式销毁方法的调用次序
优先后处理器销毁,即 @PreDestroy
其次 DisposableBean 接口销毁
最后 destroyMethod 销毁(包括自定义名称,推断名称,AutoCloseable 接
口 多选一)
 

你真正了解Spring的工作原理吗的更多相关文章

  1. Spring MVC工作原理(好用版)

    Spring MVC工作原理 参考: SpringMVC工作原理 - 平凡希 - 博客园https://www.cnblogs.com/xiaoxi/p/6164383.html SpringMVC的 ...

  2. Spring Session工作原理

    本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/KCOFv0nRuymkX79-RZi9eg 作者:张正林 目录:1.引入背景2.使用方法3.工作流程 ...

  3. Struts1、Struts2、Hibernate、Spring框架工作原理介绍

    Struts1工作原理 Struts1工作原理图 1.初始化:struts框架的总控制器ActionServlet是一个Servlet,它在web.xml中配置成自动启动的Servlet,在启动时总控 ...

  4. Spring MVC工作原理及源码解析(三) HandlerMapping和HandlerAdapter实现原理及源码解析

    1.HandlerMapping实现原理及源码解析 在前面讲解Spring MVC工作流程的时候我们说过,前端控制器收到请求后会调⽤处理器映射器(HandlerMapping),处理器映射器根据请求U ...

  5. Spring MVC工作原理及源码解析(一) MVC原理介绍、与IOC容器整合原理

    MVC原理介绍 Spring MVC原理图 上图是Spring MVC工作原理图(图片来自网上搜索),根据上图,我们可以得知Spring MVC的工作流程如下: 1.用户(客户端,即浏览器)发送请求至 ...

  6. 深入理解Spring IOC工作原理

    为什么会出现spring,spring出现解决了什么问题? 1.分析普通多层架构存在的问题 JSP->Servlet->Service->Dao 层与层之间的依赖很强,属于耦合而且是 ...

  7. Spring MVC工作原理 及注解说明

    SpringMVC框架介绍 1) spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面. Spring 框架提供了构建 Web 应用程序的全功 ...

  8. Spring的工作原理核心组件和应用

    Spring框架 Spring 是管理多个java类的容器框架,注意是类不管理接口. Spring 的主要功能 Ioc 反转控制和 DI 依赖注入. 注入的方式可以是构造函数赋值也可以是 set方法赋 ...

  9. 简述spring的工作原理

    建议不要硬着头皮看spring代码,本身的代码800多m,就是不上班开始看也不知道什么时候看完.如果想学学ioc,控制反转这些建议看看jodd项目,比较简练,但是我仍然不建议过多的看这些框架的代码,因 ...

  10. Java:Spring @Transactional工作原理

    本文将深入研究Spring的事务管理.主要介绍@Transactional在底层是如何工作的.之后的文章将介绍: propagation(事务传播)和isolation(隔离性)等属性的使用 事务使用 ...

随机推荐

  1. 以SQLserver为例的Dapper详细讲解

    Dapper是一种轻量级的ORM(对象关系映射)工具,它提供了高效且易于使用的方式来执行数据库操作.Dapper是由Stack Overflow团队开发并维护的,它的主要目标是提供比EF更快.更直接的 ...

  2. 「学习笔记」SPFA 算法的优化

    与其说是 SPFA 算法的优化,倒不如说是 Bellman-Ford 算法的优化. 栈优化 将原本的 bfs 改为 dfs,在寻找负环时可能有着更高效的效率,但是最坏复杂度为指数级别. void df ...

  3. 实例化对象 A a = new A();

    "new" 在Java中代表实例化的意思, A a = new A()代表实例化了一个对象a, 这个对象a属于A类. 可以认为A是一个抽象概念, 对象a是一个实体(存储于内存), ...

  4. MySQL-分组函数ROLLUP的基本用法

    一.ROLLUP简介 ROLLUP是GROUP BY子句的扩展. ROLLUP选项允许包含表示小计的额外行,通常称为超级聚合行,以及总计行. 通过使用ROLLUP选项,可以使用单个查询生成多个分组集. ...

  5. 2022-11-20:小团生日收到妈妈送的两个一模一样的数列作为礼物! 他很开心的把玩,不过不小心没拿稳将数列摔坏了! 现在他手上的两个数列分别为A和B,长度分别为n和m。 小团很想再次让这两个数列变

    2022-11-20:小团生日收到妈妈送的两个一模一样的数列作为礼物! 他很开心的把玩,不过不小心没拿稳将数列摔坏了! 现在他手上的两个数列分别为A和B,长度分别为n和m. 小团很想再次让这两个数列变 ...

  6. 2021-11-06:3的幂。给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。整数 n 是 3 的幂次方需满足:存在整数 x 使得 n ==

    2021-11-06:3的幂.给定一个整数,写一个函数来判断它是否是 3 的幂次方.如果是,返回 true :否则,返回 false .整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == ...

  7. Module not found: Error: Can't resolve 'axios' in 'D:\BaiduSyncdisk\vue-cli-project\dc_vue3\src\utils'

    Module not found: Error: Can't resolve 'axios' in 'D:\BaiduSyncdisk\vue-cli-project\dc_vue3\src\util ...

  8. weex create test-app Error: Cannot find module '../package.json'

    weex create 报错 D:\YLKJPro>weex create test-app Error: Cannot find module '../package.json' at Fun ...

  9. .NET周报 【5月第4期 2023-05-27】

    国内文章 C#使用词嵌入向量与向量数据库为大语言模型(LLM)赋能长期记忆实现私域问答机器人落地之openai接口平替 https://www.cnblogs.com/gmmy/p/17430613. ...

  10. 在.net项目中添加Husky.Net提交验证

    参考:C# 项目添加 husky - jesn - 博客园 (cnblogs.com) 官方文档:Getting Started | Husky.Net (alirezanet.github.io) ...