一 : spring-aop
(一) 概述
Aop是oop在编码结构上的补充, 研究的是同一层面的相同功能
横向开发
适用场景
- 事务管理
- 日志记录
- 性能统计
- 权限校验
(二) 概念
Target object : 目标对象, 需要被增强的对象
Join point : 连接点, 可以被增强的方法
Pointcut : 切入点, 确定要被增强的方法
Advice : 通知(建言), 具体的增强内容
Aspect : 切面, 切入点 + 通知 = 切面
Introduction : 引介, 可以动态的为目标对象添加属性或者是方法(特殊的通知)
Weaving : 织入, 运行期间动态的目标对象和切面结合起来的过程
AOP proxy : 动态代理
(三) 通知的类型
Before advice : 前置通知
After returning advice : 后置通知
After throwing advice : 异常通知
After (finally) advice : 最终通知
Around advice : 环绕通知
(四) Xml实现
- 添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
- 编写目标对象
@Service("killService")
public class KillerServiceImpl implements KillerService {
@Override
public void kill() {
System.out.println("杀人");
}
}
- 编写通知类
public class KillerAdvice {
public void before(){
System.out.println("前置..");
}
public void afterReturning(){
System.out.println("后置...");
}
public void atfterThrowing(){
System.out.println("异常...");
}
public void after(){
System.out.println("最终...");
}
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕前...");
Object proceed = proceedingJoinPoint.proceed();
System.out.println("环绕后...");
return proceed;
}
}
- 织入(生成代理对象)
<bean class="com.ujiuye.demo.service.impl.KillerServiceImpl" id="killerService"/>
<bean class="com.ujiuye.demo.advice.KillerAdvice" id="killerAdvice"/>
<aop:config>
<aop:pointcut id="px" expression="execution(* *..*.kill(..))"/>
<aop:aspect ref="killerAdvice">
<aop:before method="before" pointcut-ref="px"/>
<aop:after method="after" pointcut-ref="px"/>
<aop:after-returning method="afterReturning" pointcut-ref="px"/>
<aop:after-throwing method="atfterThrowing" pointcut-ref="px"/>
<aop:around method="around" pointcut-ref="px"/>
</aop:aspect>
</aop:config>
5.测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class KillerTest {
@Autowired
private KillerService killerService;
@Test
public void test(){
killerService.kill();
}
}
(五) 注解实现
- 编写目标对象
- 编写切面
- 编写配置文件
(六) 切点表达式
( * )匹配任意个字符
( . )匹配一级包的路径
( . . )匹配一级或多级包路径, 如果放在传参列表中表示可变参数
二 : 声明式事务
(一) 概述
事务是操作数据的一个逻辑单元
事务的特性
- 原子性: 表示该操作是最小动作单元, 要么同时成功要么同时失败
- 隔离性: 事务之间互不干扰互不影响
- 一致性: 事务操作前后总数不变
- 持久性: 事务提交后, 将结果永久的保存下来
(二) Spring中的事务控制
编程式: 手动编写代码对事务的处理进行控制
声明式: 显示的标明该操作被事务管理了 --> spring来进行管理
声明式事务的底层是依赖AOP的, 也就是说在方法执行前开启事务, 方法执行完毕后进行事务的提交或者是回滚
优点: 将业务逻辑和事务管理分离, 使得我们只需要专注于业务逻辑即可
缺点: 事务管理的粒度, 只能是方法级
(三) 核心API
-
platformTransactionManager
获取事务的状态
提交
回滚 -
transactionStatus
是否是新事物
是否有回滚点
设置为回滚事务
是否已完成 -
transactionDefinition
Propagation: 传播
Isolation: 隔离
readOnly: 只读
Timeout: 超时
传播行为
可以简单的理解三者的关系:事务管理器通过读取事务定义参数进行事务管理,然后会产生一系列的事务状态
(四) 声明式事务的底层原理
(五) Xml实现
- 编写dao
@Repository
public class UserDaoImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void JianMoney(int from, double money) {
jdbcTemplate.update("update user set money=money-? where id=?",money,from);
}
@Override
public void AddMoney(int to, double money) {
jdbcTemplate.update("update user money=money+? where id=?",money,to);
}
}
- 编写service
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public void updateMoney(int from, int to, double money) {
userDao.JianMoney(from,money);
int i=1/0;
userDao.AddMoney(to,money);
}
}
- 编写配置文件
<context:component-scan base-package="com.ujiuye.demo"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///offcn?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value=""/>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice transaction-manager="transactionManager" id="interceptor">
<tx:attributes>
<tx:method name="updateMoney"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pc" expression="execution(* *..*.updateMoney(..))"/>
<aop:advisor advice-ref="interceptor" pointcut-ref="pc"/>
</aop:config>
- 测试
public class UserTest {
@Autowired
private UserService userService;
@Test
public void test(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
userService = (UserService) applicationContext.getBean("userService");
userService.updateMoney(1,2,500);
}
}
(六) 注解实现
- 配置文件开启注解驱动
<tx:annotation-driven/>
- 在需要事务管理的方法或者类上添加注解即可
添加在方法上表示该方法被事务管理
添加在类上表示该类中的每个方法都被事务管理