
作用
添加依赖
-------------------------------------------------------- org.springframework spring-context5.3.18 org.aspectj aspectjweaver1.9.4
public class MyAdvice {
public void method(){
System.out.println(System.currentTimeMillis());
}
}
知识点1:@EnableAspectJAutoProxy
知识点2:@Aspect
知识点3:@Pointcut
空白 需要重新学习 ---------------黑马视频 P31
4.AOP配置管理 1.AOP切入点表达式 1.语法格式execution(public User com.itheima.service.UserService.findById(int))
execution(public * com.itheima..UserService.find(*))
匹配com.itheima包下的任意包中的UserService类或接口中所有find开头的带有一个参数的方法
execution(public User com…UserService.findById(…))
匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法
execution(void com.itheima.dao.BookDao.update()) 匹配接口,能匹配到 execution(void com.itheima.dao.impl.BookDaoImpl.update()) 匹配实现类,能匹配到 execution(* com.itheima.dao.impl.BookDaoImpl.update()) 返回值任意,能匹配到 execution(* com.itheima.dao.impl.BookDaoImpl.update(*)) 返回值任意,但是update方法必须要有一个参数,无法匹配,要想匹配需要在update接口和实现类添加参数 execution(void com.*.*.*.*.update()) 返回值为void,com包下的任意包三层包下的任意类的update方法,匹配到的是实现类,能匹配 execution(void com.*.*.*.update()) 返回值为void,com包下的任意两层包下的任意类的update方法,匹配到的是接口,能匹配 execution(void *..update()) 返回值为void,方法名是update的任意包下的任意类,能匹配 execution(* *..*(..)) 匹配项目中任意类的任意方法,能匹配,但是不建议使用这种方式,影响范围广 execution(* *..u*(..)) 匹配项目中任意包任意类下只要以u开头的方法,update方法能满足,能匹配 execution(* *..*e(..)) 匹配项目中任意包任意类下只要以e结尾的方法,update和save方法能满足,能匹配 execution(void com..*()) 返回值为void,com包下的任意包任意类任意方法,能匹配,*代表的是方法 execution(* com.itheima.*.*Service.find*(..)) 将项目中所有业务层方法的以find开头的方法匹配 execution(* com.itheima.*.*Service.save*(..)) 将项目中所有业务层方法的以save开头的方法匹配3.书写技巧
对于切入点表达式的编写其实是很灵活的,那么在编写的时候,有没有什么好的技巧让我们用用:
1.前置通知
2.后置通知
3.环绕通知------重点
基本使用
注意事项
4.返回后通知
注意:返回后通知是需要在原始方法select正常执行后才会被执行,如果select()方法执行的过程中出现了异常,那么返回后通知是不会被执行。后置通知是不管原始方法有没有抛出异常都会被执行。这个案例大家下去可以自己练习验证下。
5.异常后通知
注意:异常后通知是需要原始方法抛出异常,可以在select()方法中添加一行代码int i = 1/0即可。如果没有抛异常,异常后通知将不会被执行。
环绕通知注意事项
获取所要执行函数所传入的参数
对于返回值,只有返回后AfterReturing和环绕Around这两个通知类型可以获取
1.环绕通知获取返回值
我们是可以直接获取,不但可以获取,如果需要还可以进行修改。
2.返回后通知获取返回值
注意:
(1)参数名的问题
(2)afterReturning方法参数类型的问题
参数类型可以写成String,但是为了能匹配更多的参数类型,建议写成Object类型
(3)afterReturning方法参数的顺序问题
对于获取抛出的异常,只有抛出异常后AfterThrowing和环绕Around这两个通知类型可以获取
Spring为了管理事务,提供了一个平台事务管理器`PlatformTransactionManager
知识点1:@EnableTransactionManagement
知识点2:@Transactional
事务管理员和事务协调员
注意:
目前的事务管理是基于DataSourceTransactionManager和SqlSessionFactoryBean使用的是同一个数据源。
(不太懂)
上面这些属性都可以在@Transactional注解的参数上进行设置。
并不是所有的异常都会回滚事务,比如下面的代码就不会回滚
public interface AccountService {
//配置当前接口方法具有事务
public void transfer(String out,String in ,Double money) throws IOException;
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional
public void transfer(String out,String in ,Double money) throws IOException{
accountDao.outMoney(out,money);
//int i = 1/0; //这个异常事务会回滚
if(true){
throw new IOException(); //这个异常事务就不会回滚
}
accountDao.inMoney(in,money);
}
}
出现这个问题的原因是,Spring的事务只会对Error异常和RuntimeException异常及其子类进行事务回顾,其他的异常类型是不会回滚的,对应IOException不符合上述条件所以不回滚
此时就可以使用rollbackFor属性来设置出现IOException异常不回滚
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(rollbackFor = {IOException.class}) ========》核心
public void transfer(String out,String in ,Double money) throws IOException{
accountDao.outMoney(out,money);
//int i = 1/0; //这个异常事务会回滚
if(true){
throw new IOException(); //这个异常事务就不会回滚
}
accountDao.inMoney(in,money);
}
}
propagation设置事务属性:传播行为设置为当前操作需要新事务
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}
事务传播行为的可选值