Spring回顾

1 Spring 概述

1.1 Spring 简介

Spring 是分层的 full-stack(全栈) 轻量级开源框架,以 IoC 和 AOP 为内核,提供了展现层 Spring MVC 和业务层事务管理等众多的企业级应⽤技术,还能整合开源众多第三⽅框架,已 经成为使⽤最多的 Java EE 企业应⽤开源框架

1.2 Spring 优势

方便解耦,简化开发
通过Spring提供的IoC容器,可以将对象间的依赖关系交由Spring进⾏控制,避免硬编码所造成的 过度程序耦合。⽤户也不必再为单例模式类、属性⽂件解析等这些很底层的需求编写代码,可以更 专注于上层的应⽤。

AOP编程的⽀持
通过Spring的AOP功能,⽅便进⾏⾯向切⾯的编程,许多不容易⽤传统OOP实现的功能可以通过 AOP轻松应付。

声明式事务的⽀持 @Transactional
可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式⽅式灵活的进⾏事务的管理,提⾼ 开发效率和质量。

⽅便程序的测试
可以⽤⾮容器依赖的编程⽅式进⾏⼏乎所有的测试⼯作,测试不再是昂贵的操作,⽽是随⼿可做的 事情。

⽅便集成各种优秀框架
Spring可以降低各种框架的使⽤难度,提供了对各种优秀框架(Struts、Hibernate、Hessian、 Quartz等)的直接⽀持。

降低JavaEE API的使⽤难度
Spring对JavaEE API(如JDBC、JavaMail、远程调⽤等)进⾏了薄薄的封装层,使这些API的使⽤ 难度⼤为降低。

源码是经典的 Java 学习范例
Spring的源代码设计精妙、结构清晰、匠⼼独⽤,处处体现着⼤师对Java设计模式灵活运⽤以及对 Java技术的⾼深造诣。它的源代码⽆意是Java技术的最佳实践的范例。

2 IOC/DI

IOC:控制反转
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想

DI:依赖注入
由容器动态的将某个依赖关系注入到组件之中。提升组件重用的频率

2.1 启动

2.1.1 Java环境下启动IoC容器

ClassPathXmlApplicationContext:从类的根路径下加载配置⽂件(推荐使⽤)
FileSystemXmlApplicationContext:从磁盘路径上加载配置⽂件
AnnotationConfigApplicationContext:纯注解模式下启动Spring容器

2.1.2 Web环境下启动IoC容器


<!--配置Spring ioc容器的配置⽂件-->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:applicationContext.xml</param-value> 
</context-param>
<!--使⽤监听器启动Spring的IOC容器-->
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

2.1.3 从配置类启动容器

<!--告诉ContextloaderListener知道我们使⽤注解的⽅式启动ioc容器-->
<context-param>
<param-name>contextClass</param-name> 
	<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

2.2 BeanFactory与ApplicationContext区别

BeanFactory是Spring框架中IoC容器的顶层接⼝,它只是⽤来定义⼀些基础功能,定义⼀些基础规范,⽽ ApplicationContext是它的⼀个⼦接⼝,所以ApplicationContext是具备BeanFactory提供的全部功能 的。

通常,我们称BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的⾼级接⼝,⽐ BeanFactory要拥有更多的功能,⽐如说国际化⽀持和资源访问(xml,java配置类)等等

2.3 实例化bean

2.3.1 纯xml模式

xsd:xml文件标签约束

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--使⽤⽆参构造函数
在默认情况下,它会通过反射调⽤⽆参构造函数来创建对象。如果类中没有⽆参构造函数,将创建 失败。-->
<bean id="userService" class="com.lagou.service.impl.TransferServiceImpl"> </bean>

<!--使⽤静态⽅法创建
在实际开发中,我们使⽤的对象有些时候并不是直接通过构造函数就可以创建出来的,它可能在创 建的过程 中会做很多额外的操作。此时会提供⼀个创建对象的⽅法,恰好这个⽅法是static修饰的 ⽅法,即是此种情 况。-->
<bean id="userService" class="com.lagou.factory.BeanFactory" factory-method="getTransferService"></bean>

<!--使⽤实例化⽅法创建
此种⽅式和上⾯静态⽅法创建其实类似,区别是⽤于获取对象的⽅法不再是static修饰的了,⽽是 类中的⼀  个普通⽅法。此种⽅式⽐静态⽅法创建的使⽤⼏率要⾼⼀些。-->
<bean id="beanFactory" class="com.lagou.factory.instancemethod.BeanFactory"></bean> 
<bean id="transferService" factory-bean="beanFactory" factory- method="getTransferService"></bean>
2.3.1.1 Bean的作用范围及⽣命周期

单例模式:singleton
对象出⽣:当创建容器时,对象就被创建了。
对象活着:只要容器在,对象⼀直活着。
对象死亡:当销毁容器时,对象就被销毁了。
⼀句话总结:单例模式的bean对象⽣命周期与容器相同。

多例模式:prototype
对象出⽣:当使⽤对象时,创建新的对象实例。 对象活着:只要对象在使⽤中,就⼀直活着。
对象死亡:当对象⻓时间不⽤时,被java的垃圾回收器回收了。
⼀句话总结:多例模式的bean对象,spring框架只负责创建,不负责销毁。

2.3.1.2 Bean标签属性

在基于xml的IoC配置中,bean标签是最基础的标签。它表示了IoC容器中的⼀个对象。换句话 说,如果⼀个对象想让spring管理,在XML的配置中都需要使⽤此标签配置,Bean标签的属性如 下:

id: 唯⼀标识。在⼀个标签内部,标识必须唯⼀。

class:创建Bean对象的全限定类名。

name:给bean提供⼀个或多个名称。多个名称⽤空格分隔。

factory-bean:指定创建当前bean对象的⼯⼚bean的唯⼀标识。当指定此属性之后, class属性失效。

factory-method:⽤于指定创建当前bean对象的⼯⼚⽅法,如配合factory-bean属性使⽤, 则class属性失效。如配合class属性使⽤,则⽅法必须是static的。

scope:⽤于指定bean对象的作⽤范围。通常情况下就是singleton。当要⽤到多例模式时, 可以配置为prototype。

init-method:⽤于指定bean对象的初始化⽅法,此⽅法会在bean对象装配后调⽤。必须是 ⼀个⽆参⽅法。

destory-method:⽤于指定bean对象的销毁⽅法,此⽅法会在bean对象销毁前执⾏。它只 能为scope是singleton时起作⽤。

2.3.1.3 DI 依赖注⼊的xml配置

依赖注⼊分类

  • 按照注⼊的⽅式分类

    • 构造函数注⼊:顾名思义,就是利⽤带参构造函数实现对类成员的数据赋值。

    • set⽅法注⼊:它是通过类成员的set⽅法实现数据的注⼊。(使⽤最多的)

  • 按照注⼊的数据类型分类

    • 基本类型和String
      注⼊的数据类型是基本类型或者是字符串类型的数据。
    • 其他Bean类型
      注⼊的数据类型是对象类型,称为其他Bean的原因是,这个对象是要求出现在IoC容器 中的。那么针对当前Bean来说,就是其他Bean了。
    • 复杂类型(集合类型)
      注⼊的数据类型是Aarry,List,Set,Map,Properties中的⼀种类型。

依赖注⼊的配置实现之构造函数注⼊
顾名思义,就是利⽤构造函数实现对类成员的赋值。

它 的使⽤要求是,类中提供的构造函数参数个数必须和配置的参数个数⼀致,且数据类型匹 配。
同时需要注意的是,当没有⽆参构造时,则必须提供构造函数参数的注⼊,否则Spring 框架会报错。

2.3.2 xml与注解相结合模式

xml+注解结合模式,xml⽂件依然存在,所以,spring IOC容器的启动仍然从加载xml开始

第三⽅jar中的bean定义在xml,⽐如德鲁伊数据库连接池 ⾃⼰开发的bean定义使⽤注解

2.3.2.1 xml中标签与注解的对应(IoC)

在这里插入图片描述

2.3.2.2 DI 依赖注⼊的注解实现⽅式

@Autowired(推荐使⽤)

@Autowired为Spring提供的注解,需要导⼊包
org.springframework.beans.factory.annotation.Autowired。

@Autowired采取的策略为按照类型注⼊

public class TransferServiceImpl {
	@Autowired
	private AccountDao accountDao; 
}

如上代码所示,这样装配会去spring容器中找到类型为AccountDao的类,然后将其注⼊进来。
这 样会产⽣⼀个问题,当⼀个类型有多个bean值的时候,会造成⽆法选择具体注⼊哪⼀个的情况

@Qualifier告诉Spring具体去装配哪个对象。这个时候我们就可以通过类型和名称定位到我们想注⼊的对象。

public class TransferServiceImpl {
	@Autowired
	@Qualifier(name="jdbcAccountDaoImpl")
	private AccountDao accountDao; 
}

@Resource
@Resource 注解由 J2EE 提供,需要导⼊包 javax.annotation.Resource。 @Resource 默认按照 ByName ⾃动注⼊。

public class TransferService {
	@Resource
	private AccountDao accountDao; 
	@Resource(name="studentDao")  
	private StudentDao studentDao; 
	@Resource(type="TeacherDao")  
	private TeacherDao teacherDao;
	@Resource(name="manDao",type="ManDao")  
	private ManDao manDao;
}    

不推荐使用
@Resource 在 Jdk 11中已经移除,如果要使⽤,需要单独引⼊jar包

2.3.3 纯注解模式

对应注解
@Configuration 注解,表名当前类是⼀个配置类

@ComponentScan 注解,替代 context:component-scan

@PropertySource,引⼊外部属性配置⽂件 @Import 引⼊其他配置类

@Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息

@Bean 将⽅法返回对象加⼊ SpringIOC 容器

2.4 IOC⾼级特性

2.4.1 lazy-Init 延迟加载

Bean的延迟加载(延迟创建)

ApplicationContext 容器的默认⾏为是在启动服务器时将所有 singleton bean 提前进⾏实例化。
提前 实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的singleton bean。

设置 lazy-init 为 true 的 bean 将不会在 ApplicationContext 启动时提前被实例化,⽽是第⼀次向容器 通过 getBean 索取 bean 时实例化的。
如果⼀个设置了⽴即加载的 bean1,引⽤了⼀个延迟加载的 bean2 ,那么 bean1 在容器启动时被实例 化,⽽ bean2 由于被 bean1 引⽤,所以也被实例化,这种情况也符合延时加载的 bean 在第⼀次调⽤ 时才被实例化的规则。

如果⼀个 bean 的 scope 属性为 scope=“pototype” 时,即使设置了 lazy-init=“false”,容器启动时也不 会实例化bean,⽽是调⽤ getBean ⽅法实例化的

应⽤场景
(1)开启延迟加载⼀定程度提⾼容器启动和运转性能
(2)对于不常使⽤的 Bean 设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean 就占 ⽤资源

2.4.2 FactoryBean 和 BeanFactory

BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的⼀个⼯⼚, 具体使⽤它下⾯的⼦接⼝类型,⽐如ApplicationContext;此处我们重点分析FactoryBean

Spring中Bean有两种,⼀种是普通Bean,⼀种是⼯⼚Bean(FactoryBean),FactoryBean可以⽣成 某⼀个类型的Bean实例(返回给我们),也就是说我们可以借助于它⾃定义Bean的创建过程。

Bean创建的三种⽅式中的静态⽅法和实例化⽅法和FactoryBean作⽤类似,FactoryBean使⽤较多,尤 其在Spring框架⼀些组件中会使⽤,还有其他框架和Spring框架整合时使⽤

2.4.3 后置处理器

Spring提供了两种后处理bean的扩展接⼝
分别为 BeanPostProcessor 和 BeanFactoryPostProcessor

⼯⼚初始化(BeanFactory)—> Bean对象
在BeanFactory初始化之后可以使⽤BeanFactoryPostProcessor进⾏后置处理做⼀些事情
在Bean对象实例化(并不是Bean的整个⽣命周期完成)之后可以使⽤BeanPostProcessor进⾏后置处 理做⼀些事情
注意:对象不⼀定是springbean,⽽springbean⼀定是个对象 SpringBean的⽣命周期

BeanPostProcessor

在这里插入图片描述

定义⼀个类实现了BeanPostProcessor,默认是会对整个Spring容器中所有的bean进⾏处理。如果要对 具体的某个bean处理,可以通过⽅法参数判断,
两个类型参数分别为Object和String,第⼀个参数是每 个bean的实例,第⼆个参数是每个bean的name或者id属性的值。所以我们可以通过第⼆个参数,来判 断我们将要处理的具体的bean。
注意:处理是发⽣在Spring容器的实例化和依赖注⼊之后。

BeanFactoryPostProcessor

BeanFactory级别的处理,是针对整个Bean的⼯⼚进⾏处理,典型应 ⽤:PropertyPlaceholderConfigurer

BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息

2.5 IOC源码深度剖析

3 AOP

AOP: Aspect oriented Programming ⾯向切⾯编程/⾯向⽅⾯编程

主要用于解决横切代码重复问题
在不改变原有业务逻辑情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复

3.1 AOP实现

3.1 使⽤XML配置

<!--
Spring基于XML的AOP配置前期准备: 在spring的配置⽂件中加⼊aop的约束
xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop 
https://www.springframework.org/schema/aop/spring-aop.xsd
Spring基于XML的AOP配置步骤:

第⼀步:把通知Bean交给Spring管理
第⼆步:使⽤aop:config开始aop的配置
第三步:使⽤aop:aspect配置切⾯
第四步:使⽤对应的标签配置通知的类型
⼊⻔案例采⽤前置通知,标签为aop:before
-->
<!--把通知bean交给spring来管理-->
<bean id="logUtil" class="com.lagou.utils.LogUtil"></bean> <!--开始aop的配置-->
<aop:config>
	<!--配置切⾯-->
	<aop:aspect id="logAdvice" ref="logUtil"> <!--配置前置通知-->
	<aop:before method="printLog" pointcut="execution(public *
	com.lagou.service.impl.TransferServiceImpl.updateAccountByCardNo(com.lagou .pojo.Account))"></aop:before>
	</aop:aspect> 
</aop:config>

<!-- 五种通知类型-->

<!--前置通知
前置通知永远都会在切⼊点⽅法(业务核⼼⽅法)执⾏之前执⾏。
出现位置:它只能出现在aop:aspect标签内部 属性:-->
<aop:before method="printLog" pointcut-ref="pointcut1"> </aop:before>

<!-- (后置通知)正常执⾏通知
出现位置:它只能出现在aop:aspect标签内部-->
<aop:after-returning method="afterReturningPrintLog" pointcut- ref="pt1"></aop:after-returning>

<!--异常通知
异常通知的执⾏时机是在切⼊点⽅法(业务核⼼⽅法)执⾏产⽣异常之后,异常通知执⾏。如果切 ⼊点⽅法执⾏没有产⽣异常,则异常通知不会执⾏。
出现位置:它只能出现在aop:aspect标签内部  -->
<aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>

<!--最终通知
最终通知的执⾏时机是在切⼊点⽅法(业务核⼼⽅法)执⾏完成之后,切⼊点⽅法返回之前执⾏。 
换句话说,⽆论切⼊点⽅法执⾏是否产⽣异常,它都会在返回之前执⾏。
出现位置:它只能出现在aop:aspect标签内部  -->
<aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>

<!-- 环绕通知
环绕通知,它是有别于前⾯四种通知类型外的特殊通知。前⾯四种通知(前置,后置,异常和最终) 它们都是指定何时增强的通知类型。⽽环绕通知,它是Spring框架为我们提供的⼀种可以通过编码的 ⽅式,控制增强代码何时执⾏的通知类型。它⾥⾯借助的ProceedingJoinPoint接⼝及其实现类, 实现⼿动触发切⼊点⽅法的调⽤。
出现位置:它只能出现在aop:aspect标签内部-->
<aop:around method="aroundPrintLog" pointcut-ref="pt1"></aop:around>

切⼊点表达式,也称之为AspectJ切⼊点表达式,指的是遵循特定语法结构的字符串,其 作⽤是⽤于对符合语法格式的连接点进⾏增强。它是AspectJ表达式的⼀部分。

3.2 使⽤XML+注解组合配置

<!--开启spring对注解aop的⽀持-->
<aop:aspectj-autoproxy/>

/**
* 模拟记录⽇志 * @author 应癫 */
@Component @Aspect
public class LogUtil {
	/**
	* 我们在xml中已经使⽤了通⽤切⼊点表达式,供多个切⾯使⽤,那么在注解中如何使⽤呢?
	* 第⼀步:编写⼀个⽅法
	* 第⼆步:在⽅法使⽤@Pointcut注解
	* 第三步:给注解的value属性提供切⼊点表达式 * 细节:
	*   1.在引⽤切⼊点表达式时,必须是⽅法名+(),例如"pointcut()"。
	*   2.在当前切⾯中使⽤,可以直接写⽅法名。在其他切⾯中使⽤必须是全限定⽅法名。 */
	@Pointcut("execution(* com.lagou.service.impl.*.*(..))") 
	public void pointcut(){}
	
	@Before("pointcut()")
	public void beforePrintLog(JoinPoint jp){ 
		Object[] args = jp.getArgs();
		System.out.println("前置通知:beforePrintLog,参数是:"+
		Arrays.toString(args));     }
		@AfterReturning(value = "pointcut()",returning = "rtValue") public void afterReturningPrintLog(Object rtValue){
			System.out.println("后置通知:afterReturningPrintLog,返回值 是:"+rtValue);
		}
		@AfterThrowing(value = "pointcut()",throwing = "e") public void afterThrowingPrintLog(Throwable e){
			System.out.println("异常通知:afterThrowingPrintLog,异常是:"+e);
	    }
		@After("pointcut()")
		public void afterPrintLog(){
			System.out.println("最终通知:afterPrintLog");
	    }
		/**
		* 环绕通知 * @param pjp * @return */
		@Around("pointcut()")
		public Object aroundPrintLog(ProceedingJoinPoint pjp){ //定义返回值
			Object rtValue = null; 
			try{
				//前置通知
				System.out.println("前置通知"); //1.获取参数
				Object[] args = pjp.getArgs();
				//2.执⾏切⼊点⽅法
				rtValue = pjp.proceed(args); //后置通知
				System.out.println("后置通知");
	        }catch (Throwable t){
				//异常通知
				System.out.println("异常通知"); t.printStackTrace();
	        }finally {
				//最终通知
				System.out.println("最终通知");
	        }
		return  rtValue;
    } 
}

3.3 使⽤纯注解配置

<!--开启spring对注解aop的⽀持-->
<aop:aspectj-autoproxy/>

@Configuration
@ComponentScan("com.lagou")
@EnableAspectJAutoProxy //开启spring对注解AOP的⽀持 
public class SpringConfiguration {
}

4 Spring 声明式事务的⽀持

编程式事务:在业务代码中添加事务控制代码,这样的事务控制机制就叫做编程式事务
声明式事务:通过xml或者注解配置的⽅式达到事务控制的⽬的,叫做声明式事务

4.1事务回顾

4.1.1 事务的概念

事务指逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。从⽽确保了数 据的准确与安全。

4.1.2 事务的四⼤特性

原⼦性(Atomicity) 指事务是不可分割的,事务中的操作要么都发⽣,要么都 不发⽣。
从操作的⻆度来描述,事务中的各个操作要么都成功要么都失败

⼀致性(Consistency) 事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。
例如转账前A有1000,B有1000。转账后A+B也得是2000。

⼀致性是从数据的⻆度来说的,(1000,1000) (900,1100),不应该出现(900,1000) 隔离性(Isolation) 事务的隔离性是多个⽤户并发访问数据库时,数据库为每⼀个⽤户开启的事务, 每个事务不能被其他事务的操作数据所⼲扰,多个并发事务之间要相互隔离。
⽐如:事务1给员⼯涨⼯资2000,但是事务1尚未被提交,员⼯发起事务2查询⼯资,发现⼯资涨了2000 块钱,读到了事务1尚未提交的数据(脏读)
持久性(Durability)
持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发⽣故障 也不应该对其有任何影响。

4.1.3 事务的隔离级别

不考虑隔离级别,会出现以下情况:(以下情况全是错误的),也即为隔离级别在解决事务并发问题

脏读:⼀个线程中的事务读到了另外⼀个线程中未提交的数据。

不可重复读:⼀个线程中的事务读到了另外⼀个线程中已经提交的update的数据(前后内容不⼀样)

场景:
员⼯A发起事务1,查询⼯资,⼯资为1w,此时事务1尚未关闭
财务⼈员发起了事务2,给员⼯A张了2000块钱,并且提交了事务
员⼯A通过事务1再次发起查询请求,发现⼯资为1.2w,原来读出来1w读不到了,叫做不可重复读

虚读(幻读):⼀个线程中的事务读到了另外⼀个线程中已经提交的insert或者delete的数据(前后条数不⼀样)

场景:
事务1查询所有⼯资为1w的员⼯的总数,查询出来了10个⼈,此时事务尚未关闭 事务2财务⼈员发起,新来员⼯,⼯资1w,向表中插⼊了2条数据,并且提交了事务 事务1再次查询⼯资为1w的员⼯个数,发现有12个⼈,⻅了⻤了

数据库共定义了四种隔离级别:
Serializable(串⾏化):可避免脏读、不可重复读、虚读情况的发⽣。(串⾏化) 最⾼

Repeatable read(可重复读):可避免脏读、不可重复读情况的发⽣。(幻读有可能发⽣) 第⼆ 该机制下会对要update的⾏进⾏加锁

Read committed(读已提交):可避免脏读情况发⽣。不可重复读和幻读⼀定会发⽣。 第三

Read uncommitted(读未提交):最低级别,以上情况均⽆法保证。(读未提交) 最低

注意:级别依次升⾼,效率依次降低
MySQL的默认隔离级别是:REPEATABLE READ
查询当前使⽤的隔离级别: select @@tx_isolation;
设置MySQL事务的隔离级别: set session transaction isolation level xxx;(设置的是当前 mysql连接会话的,并不是永久改变的)

注意:级别依次升⾼,效率依次降低
MySQL的默认隔离级别是:REPEATABLE READ
查询当前使⽤的隔离级别: select @@tx_isolation;
设置MySQL事务的隔离级别: set session transaction isolation level xxx;(设置的是当前 mysql连接会话的,并不是永久改变的)

4.1.4 事务的传播行为

常用 前两种
在这里插入图片描述

4.2 声明式事务配置

4.2.1 xml

<tx:advice id="txAdvice" transaction-manager="transactionManager"> 
	<!--定制事务细节,传播⾏为、隔离级别等-->
	<tx:attributes>
		<!--⼀般性配置-->
		<tx:method name="*" read-only="false"
		propagation="REQUIRED" isolation="DEFAULT" timeout="-1"/>
		<!--针对查询的覆盖性配置-->
		<tx:method name="query*" read-only="true"
		propagation="SUPPORTS"/>
	</tx:attributes> 
</tx:advice>

<aop:config>
	<!--advice-ref指向增强=横切逻辑+⽅位-->
	<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))"/>
</aop:config>

4.2.2 xml+注解

<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManage r">
	<property name="dataSource" ref="dataSource"></property> 
</bean>
<!--开启spring对注解事务的⽀持-->
<tx:annotation-driven transaction-manager="transactionManager"/>

在接⼝、类或者⽅法上添加@Transactional注解
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)

4.2.3 纯注解

Spring基于注解驱动开发的事务控制配置,只需要把 xml 配置部分改为注解实现。
只是需要⼀个 注解替换掉xml配置⽂件中的 <tx:annotation-driven transaction-manager=“transactionManager”/>配置。
在 Spring 的配置类上添加 @EnableTransactionManagement 注解即可

@EnableTransactionManagement//开启spring注解事务的⽀持
public class SpringConfiguration {
}

4.2.3 纯注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值