切入点:匹配连接点的式子,能代表一个或者多个方法
连接点:程序中执行仍一位置,理解为方法的执行
通知:在切入点执行的操作,是共性功能
通知类:定义通知类
切面:描述通知与切入点的对应关系
注解关系:
@EnableAspectJAutoProxy(aop注解代理自动配置)-->@Aspect(作为aop的类)-->@Pointcut()@Before
@Aspect//
public class MyAdvice {
// 定义切入点,excution执行的意思,void是update方法的返回值uodata()里面无参不需要加..,反之需要加
@Pointcut("execution(void com.example.dao.BookDao.update())")
public void pt(){
}
// 定义通知
@Before("pt()") //切面
public void method(){
System.out.println(System.currentTimeMillis());
}
}
1,Spring容器启动
2,读取所有配置的切入点
3,初始化bean判断类中的方法是否匹配到切入点
匹配失败,创建对象
匹配成功,创建原始对象(目标对象)的代理对象
4,获取bean执行方法
获取bean,调用方法执行,完成
获取的bean是代理对象,就根据代理的运行模式运行原始方法活着增强的内容,完成操作
***创建的对象虽然一样,但是匹配成功后的是代理运行的,通过BookDao的getClass可以发现
切入点表达式:
前置通知:**
后置通知:**
异常通知:**
环绕通知:(重点)
// 定义通知
@Around("pt()") //环绕通知Proceedingjoinpoint 继承了 JoinPoint。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。
public Object method(ProceedingJoinPoint pjt) throws Throwable {
System.out.println("Before>>>>");
Object proceed = pjt.proceed();//需要暴露接入点的方法,否则不会执行
System.out.println("After>>>>");
return proceed;
}
//加到spring容器中
@Component
@Aspect
public class projectAdvice {
// 设置切入点
@Pointcut("execution(* com.example.sevice.*Service.*(..))")
public void pt(){
};
// 设置切面
@Around("projectAdvice.pt()")
public Object timeLength(ProceedingJoinPoint pjt) throws Throwable {
long l = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
pjt.proceed();
}
long l1 = System.currentTimeMillis();
long length = l1-l;
System.out.println(pjt.getSignature()); //获得签名
System.out.println(pjt.getSignature().getDeclaringTypeName());
System.out.println("业务的运行10000次的时间是:"+length);
return 100;
}
}
实现业务:
@Repository
public class UserDaoImpl implements UserDao {
@Override
public boolean equals(String url, String code) {
return code.equals("root");
}
}
aop操作:
@Component
@Aspect
public class dataAspectj {
// 设置切点
@Pointcut("execution(boolean com.wlb.service.UserService.equalscode(..))")
public void po(){
};
// 设置切面
@Around("dataAspectj.po()")
public Object aspect1(ProceedingJoinPoint pjt) throws Throwable {
// 获取传入的参数
Object[] args = pjt.getArgs();
// 遍历参数
for (int i = 0; i < args.length; i++) {
if(args[i].getClass().equals(String.class)){ //如果是字符串
args[i] = args[i].toString().trim();
}
}
// 返回方法重置
return pjt.proceed(args);
}
}
@EnableTransactionManagement //开启事务注解
/**
* import org.springframework.jdbc.datasource.DataSourceTransactionManager
* *调用jdbc的事务管理
* @param dataSource
* @return
*/
@Bean
public PlatformTransactionManager platformTransactionManager(DataSource dataSource){
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
//开启默认注解
@Transactional
timeout readonly等
属性:重点rollbackFor
error系列,运行时异常才会回滚,其他都不回滚
rollbackFor(**.class) 意思是遇到括号中的情况会回滚
举例:这种类型不会回滚,需要
@Transactional(rollbackFor ={Exception.class} )
@Override
public void money(String out, String in, int money) throws Exception {
accountDao.addMoney(in,money);
if(true){
throw new Exception("运行错误");
}
accountDao.reduceMoney(out,money);
}
1,这种情况不会记录日志,因为三个协调员事务都合并到管理员的事务中去了,要么都执行,要么都不执行。
2,这种情况会记录日志
@Transactional(propagation = Propagation.REQUIRES_NEW)
void log(String out,String in,int money);
使得,这个额外的日志事务不参与其他三个日志,无论他们是否异常,日志事务都会运行。