Java后端高频知识点学习笔记10---Spring
Java后端高频知识点学习笔记10---Spring
参考地址:牛 _ 客 _ 网
https://www.nowcoder.com/discuss/819319
1、什么是IOC(控制反转)和 AOP(面向切面编程)
IOC
IOC,Inversion of Control,控制反转
目的:将创建对象的控制权转移给Spring框架来进行管理
优点:IOC(控制反转)可以帮助我们维护对象与对象之间的依赖关系,降低对象之间的耦合度;如果自己创建对象的话,需要维护对象与对象之间的依赖关系,很容易造成对象之间的耦合度过高;
IOC是通过依赖注入(Dependency Injection,DI)来实现的,Spring容器负责创建应用程序中的Bean,并通过依赖注入协调这些对象之间的关系
依赖注入的方法有3种
- setter()方法注入
- 构造方法注入
- 接口注入
Spring IOC 容器的设计主要基于 BeanFactory 和 ApplicationContext 两个接口来创建Bean
AOP
Aspect Oriented Programming,AOP,面向切面编程,AOP采用横向抽取机制,将分散在各个方法中的重复代码提取出来,然后在程序编译或运行时,再将这些提取出来的代码织入到需要执行的地方
AOP实现的关键在于代理模式
- AOP代理主要分为 静态代理 和 动态代理
- 静态代理的代表为AspectJ,AspectJ是静态代理,也称为编译时增强,AOP框架会在编译阶段生成AOP代理类,并将AspectJ(切面)织入到Java字节码中,运行的时候就是增强之后的AOP对象
- 动态代理则以Spring AOP为代表,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是每次运行时在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法
JDK动态代理:这是Java提供的动态代理技术,可以在运行时创建接口的代理实例;Spring AOP默认采用这种方式,在接口的代理实例中织入代码
CGLib动态代理:采用底层的字节码技术,在运行时创建子类代理的实例;当目标对象不存在接口时,Spring AOP就会采用这种方式,在子类实例中织入代码
2、Spring Bean的生命周期
对于普通的Java对象,当new的时候创建对象,当它没有任何引用的时候被垃圾回收机制回收,
而由Spring IoC容器托管的对象,它们的生命周期完全由容器控制;Spring中每个Bean的生命周期如下
1、Spring 对bean进行实例化,默认是 单例模式
对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。 对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。 容器通过获取BeanDefinition对象中的信息进行实例化。并且这一步仅仅是简单的实例化,并未进行依赖注入。 实例化对象被包装在BeanWrapper对象中,BeanWrapper提供了设置对象属性的接口,从而避免了使用反射机制设置属性。
2、Spring 对bean进行依赖注入
实例化后的对象被封装在BeanWrapper对象中,并且此时对象仍然是一个原生的状态,并没有进行依赖注入;紧接着,Spring根据BeanDefinition中的信息进行依赖注入;并且通过BeanWrapper提供的设置属性的接口完成依赖注入
紧接着,Spring会检测该对象是否实现了xxxAware接口,并将相关的xxxAware实例注入给bean
3、如果 bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法
4、如果 bean实现了BeanFactoryAware接口,spring将调用setBeanFactory()方法,将BeanFactory实例传进来
5、如果 bean实现了ApplicationContextAware接口,它的setApplicationContext()方法将被调用,将应用上下文的引用传入到 bean 中
6、如果 bean实现了BeanPostProcessor接口,它的postProcessBeforeInitialization()方法(预初始化方法)将被调用
当经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现。 该接口提供了两个函数:
- postProcessBeforeInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会先于InitialzationBean执行,因此称为前置处理。 所有Aware接口的注入就是在这一步完成的
- postProcessAfterInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会在InitialzationBean完成后执行,因此称为后置处理。
7、如果 bean 实现了InitializingBean接口,spring将调用它的afterPropertiesSet()方法,类似的如果bean使用了init-method属性声明了初始化方法,该方法也会被调用
当BeanPostProcessor的前置处理完成后就会进入本阶段。 InitializingBean接口只有一个函数:
- afterPropertiesSet()
这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。 若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。
8、如果 bean实现了BeanPostProcessor接口,它的postProcessAfterInitialization()方法(后初始化方法)将被调用
9、此时 bean已经准备就绪,可以被应用程序使用了,他们将一直驻留在应用上下文中,直到该应用上下文被销毁
10、若bean实现了DisposableBean接口,spring将调用它的distroy()接口方法;同样的,如果bean使用了 destroy-method属性 声明了销毁方法,则该方法被调用
和init-method一样,通过给destroy-method指定函数,就可以在bean销毁前执行指定的逻辑。
3、Spring中Bean的作用域
默认情况下,Bean在Spring容器中是单例的(singleton),可以通过@Scope注解或者配置文件中的scope属性设置Bean的作用域
① singleton:在Spring容器中仅存在一个这个Bean的实例;一个Bean定义对应一个对象实例
② prototype:一个bean定义对应多个对象实例;每次调用getBean()时,都会执行new操作,返回一个新的Bean实例
③ request:每次Http请求都会创建一个新的Bean,该作用域仅在当前HTTP Request内有效
④ session:同一个Http Session共享一个Bean,不同Http Session使用不同的Bean。该作用域仅在当前 HTTP Session 内有效
⑤ global session:在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例;该作用域仅在使用 portlet context 时有效
4、Spring事务的基本实现
Spring事务管理基于AOP;事务管理类DataSourceTransactionManager本质就是一个切面类Aspect;切点就是service层里的方法;当service里的事务发生异常没有完全执行时,DataSourceTransactionManager的异常增强对事务进行了回滚(rollback);当事务完全执行完毕,DataSourceTransactionManager的后置增强对事物进行了提交commit
Spring支持两种事务编程模型:
-
1、编程式事务
Spring提供了TransactionTemplate模板,利用该模板我们可以通过编程的方式实现事务管理,而无需关注资源获取、复用、释放、事务同步及异常处理等操作;相对于声明式事务来说,这种方式相对麻烦一些,但是好在更为灵活,我们可以将事务管理的范围控制的更为精确 -
2、声明式事务
Spring事务管理的亮点在于声明式事务管理,它允许我们通过声明的方式,在IoC配置中指定事务的边界和事务属性,Spring会自动在指定的事务边界上应用事务属性;相对于编程式事务来说,这种方式十分的方便,只需要在需要做事务管理的方法上,增@Transactional注解,以声明事务特征即可;或者通过XML的方式声明式事务管理
5、Spring中使用了哪些设计模式
1、工厂模式:Spring通过BeanFactory、ApplicationContext创建Bean对象
2、代理模式:Spring AOP 功能的实现
3、单例模式:Spring 中 Bean默认都是单例的(Singleton)
4、模板方法模式:Spring中jdbcTemplate等以Template结尾的对数据库操作的类,它们就使用到了模板模式
5、观察者模式:Spring 事件驱动模型就是观察者模式很经典的一个应用
6、适配器模式:Spring AOP 的增强或通知(Advice)使用到了适配器模式,Spring中的AOP中AdvisorAdapter类;Spring MVC中的HandlerAdapter使用了适配器模式
7、装饰者模式:Spring中配置DataSource的时候,DataSource可能是不同的数据库和数据源。我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源
8、策略模式:Spring中的资源访问接口Resource接口就是基于策略设计模式实现的
6、Sping、SpringMVC、SpringBoot的区别
Spring框架就像一个家族,有众多衍生产品例如boot、security、jpa等等;但他们的基础都是Spring 的 IOC 和 AOP,IOC提供了依赖注入的容器,AOP解决了面向切面编程,然后在此两者的基础上实现了其他延伸产品的高级功能
Spring MVC提供了一种轻度耦合的方式来开发web应用;它是Spring的一个模块,是一个web框架;通过 DispatcherServlet,ModelAndView 和 View Resolver,开发web应用变得很容易;解决的问题领域是 网站应用程序或者服务开发;URL路由、Session、模板引擎、静态Web资源等等
Spring Boot实现了 auto-configuration 自动配置(另外三大神器actuator监控,cli命令行接口,starter依赖),降低了项目搭建的复杂度;主要是为了解决使用Spring框架需要进行大量的配置太麻烦的问题,所以它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具;同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box)
7、注解 @Autowired 和 @Resource 有什么区别
1、@Autowired是Spring提供的注解;@Resource是JDK提供的注解
2、@Autowired是只能按类型注入;@Resource默认按名称注入,也支持按类型注入
3、@Autowired按类型装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许null值,可以设置它required属性为false,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用
4、@Resource有两个中重要的属性:name和type;name属性指定byName,如果没有指定name属性,当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象,当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象;要注意的是,@Resource如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时,@Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了
8、Mybatis怎么通过xml绑定到接口上,具体流程
通过xml文件中,
9、介绍下Spring MVC的执行流程
1、用户通过客户端向服务端发起一个request请求,此请求会被前端控制器(DispatcherServlet)所拦截
2、前端控制器(DispatcherServlet)请求处理映射器(HandlerMapping)去查找Handler,可以依据XML配置或注解去查找
3、处理映射器(HandlerMapping)根据请求URL找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成),并返回给前端控制器
4、前端控制器(DispatcherServlet)请求处理器适配器(HandlerAdapter)去执行相应的Handler(常称为Controller)
5、处理器适配器(HandlerAdapter)会调用并执行Handler处理器,这里的处理器指的是程序中编写的Controller类,也被称为后端控制器
6、Controller执行完毕后会返回给处理器适配器(HandlerAdapter)一个ModelAndView对象,该对象中会包含View视图信息或包含 Model数据模型 和 View视图 信息
7、处理器适配器(HandlerAdapter)接收到Controller返回的ModelAndView后,将其返回给前端控制器
8、前端控制器(DispatcherServlet)接收到ModelAndView后,选择一个合适的视图解析器(ViewReslover)对视图进行解析
9、视图解析器(ViewReslover)解析后,会根据View视图信息匹配到相应的视图结果,反馈给前端控制器
10、前端控制器收到View视图后,进行视图渲染,将模型数据(在ModelAndView对象中)填充到request域
11、前端控制器向用户响应结果
10、MyBatis是什么?它的优点是什么?
MyBatis 是一款 优秀的持久层框架,它支持 自定SQL、存储过程以及高级映射
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作
MyBatis 可以通过简单的 XML 或 注解 来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
MyBatis的优点:
- 1、sql语句与代码分离,存放于xml配置文件中,解除SQL和程序代码的耦合,便于统一管理和优化,并可重用
- 2、支持编写动态SQL语句
- 3、支持对象与数据库的ORM字段关系映射
【ORM:对象关系映射(Object Relational Mapping,简称 ORM)】
11、MyBatis中的${}和#{}有什么区别
-
{}:在预编译时,会把参数部分用一个占位符?(问号)代替,传入的内容会被作为字符串,被加上引号,安全性高,可以防止sql注入
- {}
什么是SQL注入?
- 所谓SQL注入式攻击:攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令
- 详细的讲,就是:SQL注入是将Web页面的原URL、表单域或数据包输入的参数,修改拼接成SQL语句,传递给Web服务器,进而传给数据库服务器以执行数据库命令;如Web应用程序的开发人员对用户所输入的数据或cookie等内容不进行过滤或验证(即存在注入点)就直接传输给数据库,就可能导致拼接的SQL被执行,获取对数据库的信息以及提权,发生SQL注入攻击
12、MyBatis缓存
MyBatis的缓存分为一级缓存和二级缓存
-
1、一级缓存: MyBatis的一级缓存是SqlSession级别的缓存,当在同一个SqlSession中执行两次相同的SQL语句时,会将第一次执行查询的数据存入一级缓存中,第二次查询时会从缓存中获取数据,而不用再去数据库中查询,从而提高了查询性能;但如果SqlSession执行insert、delete和update操作,并提交到数据库或者SqlSession结束后,这个SqlSession中的一级缓存就不存在了
-
2、二级缓存: MyBatis的二级缓存是SqlSessionFactory级别的缓存,由同一个SqlSessionFactory对象创建的sqlsession共享其缓存
-
一级缓存:也称为本地缓存,用于保存用户在一次会话过程中查询的结果,用户一次会话中只能使用一个sqlSession,一级缓存是自动开启的,不允许关闭
-
二级缓存:也称为全局缓存,是mapper级别的缓存,是针对一个表的查结果的存储,可以共享给所有针对这张表的查询的用户。也就是说对于mapper级别的缓存不同的sqlsession是可以共享的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程