Spring基础

Spring基础

Spring能做什么:用以开发web、微服务以及分布式系统等。光这三块就已经占了JavaEE开发的九成多。
Spring框架主要的优势是在简化开发和框架整合上:
简化开发: Spring两大核心技术IOC、AOP。
事务处理属于Spring中AOP的具体应用,可以简化项目中的事务管理,也是Spring技术中的一大亮点。

系统架构讲究上层依赖下层,所以越下层越核心,最下层的是核心容器。

(1)核心层
Core Container:核心容器,这个模块是Spring最核心的模块,其他的都需要依赖该模块
(2)AOP层
AOP(Aspect Oriented Programming,aspect译为切面,方面;oriented译为面向,以…为方向;):面向切面编程。它依赖核心层容器,目的是在不改变原有代码的前提下对其进行功能增强
Aspects:AOP是思想,Aspects是对AOP思想的具体实现
(3)数据层
Data Access:数据访问,Spring全家桶中有对数据访问的具体实现技术
Data Integration:数据集成,Spring支持整合其他的数据层解决方案,比如Mybatis。integration译为集成,结合,融合。
Transactions:事务,Spring中事务管理是Spring AOP的一个具体实现,也是后期学习的重点内容。Transactions译为事务,业务,交易。
(4)Web层
这一层的内容将在SpringMVC框架具体学习
(5)Test层
Spring主要整合了Junit来完成单元测试和集成测试
在Spring核心概念这部分内容中主要包含IOC/DI、IOC容器和Bean

IOC控制反转

对象创建控制权由程序转移到外部(IOC容器),此思想称为控制反转,外部由Spring提供,即IOC容器。
IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象,被创建或被管理的对象在IOC容器中统称为Bean
service运行需要依赖dao对象(data access object数据访问对象),IOC容器中虽然有这两种对象,但二者没有联系起来,绑定service和dao对象之间的关系需要用到DI依赖注入

DI依赖注入

在容器中绑定bean与bean之间的依赖关系的整个过程,称为依赖注入

Bean

在这里插入图片描述
为什么bean默认为单例?
bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象
bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高
bean在容器中是单例的,会不会产生线程安全问题?
如果对象是有状态对象(该对象有成员变量可以用来存储数据的)
因为所有请求线程共用一个bean对象,所以会存在线程安全问题。
如果对象是无状态对象(该对象没有成员变量没有进行数据存储的,不建议存在IOC容器中)
因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题。
哪些bean对象适合交给容器进行管理?
表现层对象
业务层对象
数据层对象
工具对象
哪些bean对象不适合交给容器进行管理?
封装实例的域对象,因为会引发线程安全问题,所以不适合。

bean的三种创建方式

构造方法,静态工厂,实例工厂(FactoryBean)

bean的生命周期

注入

构造器注入遇到紧耦合(形参名)问题,type属性,index属性
依赖注入方式选择
强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现。强制依赖指对象在创建的过程中必须要注入指定的参数。
可选依赖使用setter注入进行,灵活性强。可选依赖指对象在创建过程中注入的参数可有可无
Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入

核心容器

容器创建的方式

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

bean的三种获取方式
根据id获取

BookDao bookDao = (BookDao) ctx.getBean("bookDao");

getBean(“名称”):需要类型转换
getBean(“名称”,类型.class):多了一个参数
getBean(类型.class):容器中不能有多个该类的bean对象

IOC/DI注解开发

注解关键字

配置类
@Configuration    //声明配置类
@ComponentScan("package1")    //组件扫描路径
@EnableAspectJAutoProxy        //开启aop
@EnableTransactionManagement    //开启业务管理
@PropertySource("classpath:jdbc.properties")        //properties配置文件路径
@Import({JdbcConfig.class,MybatisConfig.class})    //导入第三方配置文件
public class SpringConfig {
}

在这里插入图片描述

IOC相关注解
@Configuration

名称 @Configuration
类型 类注解
位置 类定义上方
作用 设置该类为spring配置类
属性 value(默认):定义bean的id
@ComponentScan

名称 @ComponentScan
类型 类注解
位置 类定义上方
作用 设置spring配置类扫描路径,用于加载使用注解格式定义的bean
属性 value(默认):扫描路径,此路径可以逐层向下扫描
DI相关注解

知识点1:@Autowired

名称 @Autowired
类型 属性注解 或 方法注解(了解) 或 方法形参注解(了解)
位置 属性定义上方 或 标准set方法上方 或 类set方法上方 或 方法形参前面
作用 为引用类型属性设置值
属性 required:true/false,定义该属性是否允许为null
知识点2:@Qualifier

名称 @Qualifier
类型 属性注解 或 方法注解(了解)
位置 属性定义上方 或 标准set方法上方 或 类set方法上方
作用 为引用类型属性指定注入的beanId
属性 value(默认):设置注入的beanId
知识点3:@Value

名称 @Value
类型 属性注解 或 方法注解(了解)
位置 属性定义上方 或 标准set方法上方 或 类set方法上方
作用 为 基本数据类型 或 字符串类型 属性设置值
属性 value(默认):要注入的属性值
知识点4:@PropertySource

名称 @PropertySource
类型 类注解
位置 类定义上方
作用 加载properties文件中的属性值
属性 value(默认):设置加载的properties文件对应的文件名或文件名组成的数组
第三方管理相关注解:

知识点1:@Bean

名称 @Bean
类型 方法注解
位置 方法定义上方
作用 设置该方法的返回值作为spring管理的bean
属性 value(默认):定义bean的id
知识点2:@Import

名称 @Import
类型 类注解
位置 类定义上方
作用 导入配置类
属性 value(默认):定义导入的配置类类名,
当配置类有多个时使用数组格式一次性导入多个配置类
aop相关注解:

知识点1:@EnableAspectJAutoProxy

名称 @EnableAspectJAutoProxy
类型 配置类注解
位置 配置类定义上方
作用 开启注解格式AOP功能
知识点2:@Aspect

名称 @Aspect
类型 类注解
位置 切面类定义上方
作用 设置当前类为AOP切面类
知识点3:@Pointcut

名称 @Pointcut
类型 方法注解
位置 切入点方法定义上方
作用 设置切入点方法
属性 value(默认):切入点表达式
aop环绕通知相关注解:

知识点4:@Before

名称 @Before
类型 方法注解
位置 通知方法定义上方
作用 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前运行
知识点5:@After

名称 @After
类型 方法注解
位置 通知方法定义上方
作用 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法后运行
知识点6:@AfterReturning

名称 @AfterReturning
类型 方法注解
位置 通知方法定义上方
作用 设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法正常执行完毕后执行
知识点7:@AfterThrowing

名称 @AfterThrowing
类型 方法注解
位置 通知方法定义上方
作用 设置当前通知方法与切入点之间绑定关系,当前通知方法在原始切入点方法运行抛出异常后执行
知识点8:@Around

名称 @Around
类型 方法注解
位置 通知方法定义上方
作用 设置当前通知方法与切入点之间的绑定关系,当前通知方法在原始切入点方法前后运行
业务相关注解:

知识点1:@EnableTransactionManagement

名称 @EnableTransactionManagement
类型 配置类注解
位置 配置类定义上方
作用 设置当前Spring环境中开启注解式事务支持
知识点2:@Transactional

名称 @Transactional
类型 接口注解 类注解 方法注解
位置 业务层接口上方 业务层实现类上方 业务方法上方
作用 为当前业务层方法添加事务(如果设置在类或接口上方则类或接口中所有方法均添加事务)

spring整合mybatis和junit

没看懂

AOP事务管理

AOP面向切面编程:抽取共性代码(即通知),植入到待增强的方法(即切入点)。
作用:在不改原有代码的前提下对代码进行增强。
切面:所谓的切面,简单来说就是与业务无关,却为业务模块所共同调用的逻辑,将其封装起来便于减少系统的重复代码,降低模块的耦合度,有利用未来的可操作性和可维护性
通知和切入点的关系。

AOP有两种实现方式:
JDK动态代理(默认):运行时创建接口的代理实例。
CGLib代码生成库动态代理:采用底层的字节码技术,当目标对象不存在接口时,创建子类代理的实例。

应用场景:日志和事务。

AOP不能增强的类:

  1. Spring AOP只能对IoC容器中的Bean进行增强,对于不受容器管理的对象不能增强。
  2. 由于CGLib采用动态创建子类的方式生成代理对象,所以不能对final修饰的类进行代理。

在这里插入图片描述
连接点(JoinPoint):bean类的原始方法
程序执行过程中的任意位置,粒度为执行方法、抛出异常、设置变量等
在SpringAOP中,理解为方法的执行
切入点(Pointcut):需要被增强的方法。匹配连接点的式子
在SpringAOP中,一个切入点可以描述一个具体方法,也可也匹配多个方法
一个具体的方法:如com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法
匹配多个方法:所有的save方法,所有的get开头的方法,所有以Dao结尾的接口中的任意方法,所有带有一个参数的方法
连接点是全部方法,切入点匹配某些需要被增强的方法。连接点范围要比切入点范围大,是切入点的方法也一定是连接点,但是是连接点的方法就不一定要被增强,所以可能不是切入点。
通知(Advice):要增强的内容,共性的方法。在切入点处执行的操作,也就是共性功能
在SpringAOP中,功能最终以方法的形式呈现
通知类:定义通知的bean类
切面(Aspect):描述通知与切入点的对应关系。把通知和切入点绑定到一块,一个通知对应一个切入点。例如切面是Before,即通知在切入点之前运行。

AOP工作流程

目标对象和代理对象?
目标对象(Target):原始功能去掉共性功能对应的类产生的对象,这种对象是无法直接完成最终工作的
代理(Proxy):目标对象无法直接完成工作,需要对其进行功能回填,通过原始对象的代理对象实现
目标对象就是还没有加入共性方法的类[如:BookServiceImpl类]对应的对象,也叫原始对象。

切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)
常用的切入点表达式:
@Pointcut(“execution(* package1.service.Service.select(…))”)
private void pt(){}
可以通配所有返回类型(void,int等)、所有业务层接口、所有select方法(select,selectXxx)、所有带参、无参类型。
切入点表达式描述通配符:

作用:用于快速描述,范围描述
*:匹配任意符号(常用)
… :匹配多个连续的任意符号(常用)
+:匹配子类类型

AOP通知类型

在这里插入图片描述(1)前置通知,追加功能到方法执行前,类似于在代码1或者代码2添加内容

(2)后置通知,追加功能到方法执行后,不管方法执行的过程中有没有抛出异常都会执行,类似于在代码5添加内容

(3)环绕通知,环绕通知功能比较强大,它可以追加功能到方法执行的前后,这也是比较常用的方式,它可以实现其他四种通知类型的功能。

(4)返回后通知,追加功能到方法执行后,只有方法正常执行结束后才进行,类似于在代码3添加内容,如果方法执行抛出异常,返回后通知将不会被添加

(5)抛出异常后通知,追加功能到方法抛出异常后,只有方法执行出异常才进行,类似于在代码4添加内容,只有方法抛出异常后才会被添加
环绕通知注意事项
环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用,进而实现原始方法调用前后同时添加通知
通知中如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行
对原始方法的调用可以不接收返回值,通知方法设置成void即可,如果接收返回值,最好设定为Object类型
原始方法的返回值如果是void类型,通知方法的返回值类型可以设置成void,也可以设置成Object
由于无法预知原始方法运行后是否会抛出异常,因此环绕通知方法必须要处理Throwable异常
因为环绕通知是可以控制原始方法执行的,所以我们把增强的代码写在调用原始方法的不同位置就可以实现不同的通知类型的功能,如:
在这里插入图片描述

百度网盘密码数据兼容处理

需求: 对百度网盘分享链接输入密码时尾部多输入的空格做兼容处理。

AOP事务管理

Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败

事务隔离级别

多个事务同时操作同一个数据库时,一个事务读取到其他事务已经提交但未持久化到数据库中的数据所带来的影响。
读取未提交内容:隔离级别最低,事务可以读取到其他未提交事务的数据;
读取已提交内容:保证其他事务提交后才能读取数据。解决脏读。
可重复读:保证在一个事务内多次查询相同数据时,结果是一致的。解决脏读、不可重复读
序列化:隔离级别最高,在整个事务过程中将所有操作串行化执行。解决脏读、不可重复读和幻读,但性能差
与数据库默认设置保持一致(默认):数据库的默认隔离级别

脏读:因为延迟等原因,第一个事务在更新数据库前,第二个事务已经更新了数据库,导致最终数据库内容是第一个事务改的情况。
不可重复读:同一次事务前后查询结果不一致;
幻读:同义词事务前后数据量发生变化,像幻觉一样。
非事务方法调用事务方法必须用代理对象调用???

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值