AOP
概述:AspectOrientedProgramming 面向切面编程:是对面向对象编程的补充延续,面向切面编程思想是将程序中非业务代码(提交事务,打印日志,权限验证,统一异常处理)
然后在调用业务代码时,通过一个代理对象帮助我们调用这些提取出来的非业务代码,这样在业务代码不用显示的调用非业务代码,做到的业务代码和非业务代码的分离,降低了耦合度。
好处:模块之间的耦合度降低了
原理:动态代理模式 给业务代码生成代理对象
AOP的基本概念
连接点(Joinpoint):类中可以被增强(加功能)的方法,这个方法就被称为连接点
切入点(pointcut):类中有很多方法可以被增强,但实际中只有add和update 被增了,那么add和update方法就被称为切入点(实际实现的连接点)
通知(Advice): 通知是指一个切面在特定的连接点要做的事情(增强的功能)。通知分为方法执行前通知,方法执行后通知,环绕通知等.
目标(Target): 代理的目标对象(连接点,切入点所在类)
代理(Proxy): 向目标对象应用通知时创建的代理对象
springAOP 实现
在pom.xml文件中导入AOP相关的jar包(AspectJ)
<!--spring aop--><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.2.RELEASE</version></dependency>
在spring.xml文件中配置开启AspectJ的自动代理
<!--开启自动代理--><aop:aspectj-autoproxy />
AspectJ中常用的通知有五种类型:
通知,向连接点添加的功能
注解实例:
1.@before()
@Before() 前置通知 在业务方法执行之前调用执行
/*execution:表达式的主体第一处*:返回的类型(这里代表所有类型)com.ffyc.springpro.dao:拦截的包名第二处*:类名第三处*:方法名(..):表示方法的参数,".."表示任意参数
*/@Before("execution(* com.ffyc.springpro.dao.*.*(..))")
public void printlog(){System.out.println("打印日志");}
2.@After()
@After() 后置通知 在业务方法执行完后调用执行 即使业务代码中出现了异常,也会执行
@After("execution(* com.ffyc.springpro.dao.*.*(..))")
public void printlog(){System.out.println("打印日志");}
3.@AfterReturning()
@AfterReturning() 返回通知 在业务方法执行完后再执行 当业务代码中出现了异常,不会执行
public void insert(){System.out.println("新增");System.out.println(10/0);}
@AfterReturning("execution(* com.ffyc.springpro.dao.*.*(..))")public void printlog(){System.out.println("打印日志");}
4.@AfterThrowing()
@AfterThrowing() 异常通知 当业务代码出现异常时,调用执行
public void insert(){System.out.println("新增");System.out.println(10/0);}
@AfterThrowing(value = "execution(* com.ffyc.springpro.dao.*.*(..))",throwing = "e")public void exception(Throwable e){System.out.println("系统忙"+e.getMessage());e.printStackTrace();}
前四个注解为一组,一并使用。
5.@Around()
@Around 环绕通知 可以在业务方法执行之前,之后,出异常时添加功能
@Around(value = "execution(* com.ffyc.springpro.dao.*.*(..))")public void around(ProceedingJoinPoint joinPoint){//ProceedingJoinPoint joinPoint 表示的是目标方法System.out.println("前置通知");try {Object[] obj = joinPoint.getArgs();//获取目标方法的参数System.out.println(Arrays.toString(obj));Object object = joinPoint.proceed();//调用目标业务方法System.out.println("返回通知");} catch (Throwable throwable) {throwable.printStackTrace();System.out.println("异常通知");}System.out.println("后置通知");}
第五种@around注解相当于将前四个注解做的一个集合。
Spring 事物管理
事务管理本质上是数据库提供的一种管理机制。
数据库事务管理是对一次数据库操作过程中执行的多条语句进行管理。
确保一次操作过程中的多条sql语句要么都执行成功,要么都不执行,从而保证数据一致性。
例如:转账: sql1 A-500 sql2 B+500 确保转账数据的一致
spring事务管理是spring框架对事务提交这一功能进行封装,程序员在业务开发中不需要显示的提交事务。
Spring中的事务管理分为两种方式:
1、编程式事务管理
需要程序员在代码中自己控制事务提交和回滚
2、声明式事务管理
声明事务底层使用了AOP思想,可以为方法添加事务功能,它的控制是方法级别的
基于注解实现的spring事务管理 Spring 框架,提供事物管理实现类是DataSourceTransactionManager.
在spring.xml文件中配置以下两个步骤
1.配置事物管理器
<!-- 配置spring 事务管理器--><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="druidDataSource"></property></bean>
2.开启注解事务管理
<!-- 开启注解事务管理--><tx:annotation-driven transaction-manager="transactionManager"/>
在类或方法上使用@Transactional标签即可.
@Transactional 可以添加在方法上,也可以添加到类上面
如果添加在类上面,此类中的所有方法都在spring事务管理中运行
声明式事务失效的情况
1.@Transactional 用在非public修饰的方法上
2.方法中的异常被捕获了,认为方法没有异常
3.方法中出现编译期异常,还是会提交事务 解决方案:@Transactional(rollbackFor = Exception.class)
4.数据库引擎不支持事务 mysql中只有innodb引擎支持事务的