spring
2021-11-13 13:31:19 47 举报
AI智能生成
Spring是一个开源的Java平台,它提供了一个轻量级的解决方案,用于开发企业级应用程序。Spring框架的主要特点是依赖注入和面向切面编程。通过依赖注入,开发人员可以将对象之间的依赖关系从硬编码中解放出来,从而提高了代码的可重用性和可维护性。面向切面编程则允许开发人员将横切关注点(如日志记录、事务管理等)与业务逻辑分离,从而实现了更好的模块化和解耦。此外,Spring还提供了许多其他功能,如集成Web服务、消息队列、缓存等。总之,Spring是一个非常强大且灵活的框架,它能够帮助开发人员快速构建高质量的企业级应用程序。
作者其他创作
大纲/内容
基本概念<br>
两个核心
控制反转
解耦<br>
切面编程<br>
以动态非侵入式方式增加服务<br>
缺点<br>
依赖反射,影响性能<br>
风格特点
面向对象编程到面向接口编程<br>
IOC
作用
管理对象的创建与维护
解耦<br>
托管类的生成过程
实现机制
工厂模式+动态代理
支持的功能<br>
依赖注入
组件之间的依赖关系由容器在应用系统运行期来决定
原则
应用组件不应该负责查找资源或者其他依赖的协作对象。<br><font color="#f15a23">配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。<br>容器全权负责组件的装配,</font>它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象。<br>
优势
查找定位操作与应用代码完全无关<br>
不依赖于容器的API,可以很容易地在任何容器以外使用应用对象
不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器
实现方式
接口注入<br>
灵活性、易用性差,spring4已废除
<u>典型应用场景:JNDI</u>
Setter方法注入
有部分注入<br>
会覆盖Setter方法
任意修改不会创建新实例<br>
适用于设置少属性
构造器注入
不会覆盖Setter方法<br>
任意修改会创建新实例<br>
适用于设置很多属性
工厂方法注入
静态工厂方法注入
属性注入(注解直接写在属性上)
利用反射,直接注入属性
单例循环依赖的问题及解决方式<br>
使用三级缓存
<b><font color="#9c27b0">三级缓存(singletonFactories</font></b> ): 单例对象工厂的cache
<font color="#9c27b0"><b>二级缓存(earlySingletonObjects</b></font> ):提前暴光的单例对象的Cache
<font color="#9c27b0"><b>一级缓存(singletonObjects):</b></font>单例对象的cache
在创建bean的时候,<br>首先从cache中获取这个单例的bean,这个缓存就是singletonObjects。<br>如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。<br>如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,如果获取到了则:从singletonFactories中移除,并放入earlySingletonObjects中。<br>
Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache
依赖检查<br>
自动装配<br>
支持集合<br>
<u>指定初始化方法和销毁</u><br>
支持回调某些方法(需要实现接口)<br>
BeanFactory,ApplicationContex<br>
BeanFactory
Spring里面最底层的接口,包含了各种Bean的定义,读取bean配置文档,管理bean的加载、实例化,控制bean的生命周期,维护bean之间的依赖关系。
<font color="#f15a23">延迟加载形式来注入Bean的</font><br>
总结
加载配置文件,解析成 BeanDefinition 放在 Map 里。<br>
调用 getBean 的时候,从 BeanDefinition 所属的 Map 里,拿出 Class 对象进行实例化,同时,如果有依赖关系,将递归调用 getBean 方法 —— 完成依赖注入。
ApplicationContex
扩展BeadFactory,更完整的框架功
继承MessageSource,因此支持国际化。
统一的资源文件访问方式。<br>
提供在监听器中注册bean的事件。
同时加载多个配置文件。<br>
载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层。
<font color="#f15a23">一次性创建了所有的Bean。</font>
总结
他不仅仅是 IoC。他支持不同信息源头,支持 BeanFactory 工具类,支持层级容器,支持访问文件资源,支持事件发布通知,支持接口回调等等。
AOP
动态代理/静态代理<br>(<font color="#f68b1f">spring采用的动态代理</font>)
动态代理(Spring AOP)
动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是<font color="#f15a23">每次运行时在内存中临时</font>为方法生成一个AOP对象,这个AOP对象包<br>含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。
静态代理(AspectJ AOP)
静态代理的增强,所谓静态代理,就是AOP框架会在编译阶段生成AOP代理类,因此也称为<font color="#f15a23">编译时增强</font>,他会在编译阶段将AspectJ(切面)织入到<br>Java字节码中,运行的时候就是增强之后的AOP对象。
方式<br>
JDK动态代理
JDK动态代理是面向接口,在创建代理实现类时比CGLib要快,创建代理速度快。
CGLIB<b>动态代理</b>
CGLib所创立的动态代理商对象在实际运行时候的性能要比JDK动态代理商高
CGLib在创立对象的时候所花费的时间却比JDK动态代理商要多很多
名词
切面Aspect
通知+切点
连接点Join Point<br>
切点Point Cut
通知Advice
切面的工作被称为通知
通知类型
<font color="#f15a23">前置通知</font><br>
<font color="#f15a23">后置通知</font>
<font color="#f15a23">返回通知</font><br>
<font color="#f15a23">异常通知</font>
<font color="#f15a23">环绕通知</font><br>
引入Introduction<br>
向现有类添加新方法或属性
目标对象Target Object<br>
织入Weawing
切面应用到目标对象并创建新的代理对象的过程
应用的生命周期<br>
编译器<br>
切面在目标类编译时被织入。<b><font color="#f15a23">AspectJ</font></b>的织入编译器是以这种方式织入切面的
类加载时期
切面在目标类加载到JVM时被织入。<br><b><font color="#f15a23">需要特殊的类加载器</font></b>,它可以在目标类被引入应用之前增强该目标类的字节码。<b><font color="#f15a23">AspectJ5的加载时织入就支持以这种方式织入切面。</font></b><br>
运行期
切面在应用运行的某个时刻被织入。<br>一般情况下,在织入切面时,AOP容器会为目标对象动态地创建一个代理对象。<b><font color="#f15a23">SpringAOP</font></b>就是以这种方式织入切面。<br>
模块
核心容器(Core Container)<br>
Bean<br>
提供BeanFactory,spring将管理对象称为bean<br>
Core
提供框架基本组件,包括控制反转与依赖注入
Context<br>
构建于core之上的context封装,提供框架式的对象访问方法<br>
SpEL<br>
切面编程(Aop,Aspects)<br>
Aop
动态代理切面编程
Aspects
静态代理切面编程<br>
设备支持(Instrumentation)<br>
数据库访问与集成(Data Access/Integration)<br>
JDBC<br>
提供JDBC抽象层<br>
ORM
OXM
JMS
Transaction<br>
Web
WebSocket<br>
Servlet<br>
Web
Portlet<br>
消息(Messaging)<br>
测试(Test)<br>
为测试提供支持,提供了Junit,Testng
spring Bean<br>
配置方式<br>
XML配置<br>
注入bean的方式<br>
Setter注入<br>
构造方法注入,①通过index设置参数的位置;②通过type设置参数类型;<br>
静态工厂注入
实例注入<br>
注解配置<br>
Java配置<br>
作用域<br>
singleton : bean在每个Spring ioc 容器中只有一个实例。<br>
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean<br>
session:在一个HTTP Session中<br>
global-session:在一个全局的HTTP Session中,<font color="#c41230">仅在基于portlet的web应用中才有意义</font>
生命周期
内部Bean<br>
内部Bean通常是匿名的,所有scope是protoType<br>
注入一个java集合<br>
直接将一个集合注册为一个Bean
自动装载Bean<br>
no
默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean
ByName
ByType
constructor<br>
利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
autodectect<br>
自动探测,如果有构造方法,通过 construct的方式自动装配,否则使用 byType的方式自动装配。
@Autowired
容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会<br>在IoC容器自动查找需要的bean,并装配给该对象的属性。
1.查找对应类型的Bean<br>
2.通过类型查找有多个,则根据名字查找<br>
3.如果都找不到抛出异常<br>
解决办法:required=false
注解
@Component
@Controller
@Service
@Repository
@Component 注解的特化,它将 DAO 导入 IoC 容器,并使未经检查的异常有<br>资格转换为 Spring DataAccessException。
@Autowired
默认类型注入,再名称
@Resource
默认名称注入,再类型
@Qualifier
创建多个相同类型的 bean 并希望仅使用属性装配其中一个 bean 时,您可以使用@Qualifier 注解和 @Autowired 通过指定应该装配哪个确切的 bean 来消除歧义。
事务
事务方式
申明式事务
简单,灵活性相对差
编程事事务<br>
难度大,灵活性好<br>
事务传播行为
PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
PROPAGATION_REQUIRES_NEW(新建事务):创建新事务,无论当前存不存在事务,都创建新事务。
PROPAGATION_SUPPORTS(根据调用方事务确定):支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
PROPAGATION_NOT_SUPPORTED(挂起已有事务):以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_MANDATORY(没有事务则抛出异常):支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
PROPAGATION_NEVER(有事务就抛出异常):以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
事务隔离行为<br>(<b>依靠数据库实现</b>)
SOLATION_DEFAULT
用底层数据库的设置隔离级别
ISOLATION_READ_UNCOMMITTED<br>
未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)
ISOLATION_READ_COMMITTED<br>
提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;
ISOLATION_REPEATABLE_READ<br>
可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造<br>成幻读),MySQL 的默认级别;
ISOLATION_SERIALIZABLE
序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读
脏读
表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。
不可重复读
是指在一个事务内,多次读<b><font color="#f15a23">同一数据</font></b>。而数据不同
幻读
指同一个事务内多<b><font color="#f15a23">次查询返回的结果集</font></b>不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。<b>发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。</b>
本质
<b>本身无法提供事务,使用的数据库事务</b><br>
五种标准的事件类型
上下文更新事件
在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。
上下文开始事件<br>
当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件
上下文停止事件
当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
上下文关闭事件<br>
当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
请求处理事件
在Web应用中,当一个http请求(request)结束触发该事件。<br>如果一个bean实现了ApplicationListener接口,当一个ApplicationEvent 被发布以后,bean会自动被通知。<br>
仅在基于web的Spring ApplicationContext情形下有效。
0 条评论
下一页