springAOP
连接点(join point):能被拦截器拦截的方法。
切点(pointcut):真正被拦截的方法。
注意:切点一定是连接点,而连接点不一定是切点,因为连接点有可能不被拦截,从而不进行增强。
通知(advice):拦截器中的方法。分为前置通知,后置通知(也称最终通知),返回通知,异常通知,环绕通知五类。以反射执行目标对象方法为基准:
- 前置通知:在目标对象方法执行之前执行;
- 后置通知(最终通知):在目标对象方法执行完成后,无论在执行过程中是否出现异常,都会执行;
- 异常通知:目标对象方法执行过程中产生异常后执行;
- 返回通知:目标对象方法执行过程中不产生异常时执行;
- 环绕通知:特殊的通知,不以目标对象方法为基准,可以同时实现前置和后置通知。环绕通知保留了调度目标对象原有方法的功能,也就是说,使用环绕通知甚至可以不必要调用目标对象方法,可以取代目标对象的方法。因此环绕通知非常强大,而且灵活,但可控性差,一般不需要大量改变业务逻辑的情况下,不会使用环绕通知。
切面(aspect):通知与切点的结合。
织入(weaving):将通知组合到目标的过程。
引入(introduction):允许在现有类中添加自定义的类和方法。
记住这个就行:
Before 方法前
AfterReturning 方法返回之后
AfterThrowing 在异常抛出后
After finally执行
Around 环绕通知
**
* 性能监测
* @return
*/
@Around("logPointcut()")
public Object performanceAdvice(ProceedingJoinPoint pjp){
//方法执行前处理
// --- 调用被拦截的方法,执行连接点(方法)---
//方法签名
Signature signature = pjp.getSignature();
//得到参数
Object[] args = pjp.getArgs();
System.out.println("进入方法"+signature+" 参数为"+ Arrays.toString(args));
try {
long before = System.currentTimeMillis();
//得到了方法调用的参数
Object result = pjp.proceed(args);
long after = System.currentTimeMillis();
System.out.println("执行时长为:"+(after-before)+"ms");
return result;
} catch (Throwable t) {
throw new RuntimeException(t);
}
//方法执行后处理
}
手写声明式事务
定义事务注解 @Tx
定义切面:
• 切入点是所有加了Tx注解的方法;
• 通知选用环绕类型
• 方法执行前开启事务
• 执行方法
• 提交或者回滚事务
第一步:加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- 将mybatis集成到spring中 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
第二步:拷贝代码,拷贝配置文件,拷贝配置类,修改配置,导入配置类
第三步:定义注解
package com.woniuxy.framework.annotations;
import java.lang.annotation.*;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Tx {
}
第四步:定义切面
package com.woniuxy.framework.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Component
@Aspect
public class TxAspect {
@Autowired
private PlatformTransactionManager platformTransactionManager;
/**
* 拦截所有加入了@Tx注解的方法
*/
@Pointcut("@annotation(com.woniuxy.framework.annotations.Tx)")
public void txPointcut(){}
/**
* 事务通知
* @param pjp
* @return
*/
@Around("txPointcut()")
public Object txAdvice(ProceedingJoinPoint pjp){
//1.开启事务
TransactionStatus txStatus = platformTransactionManager.getTransaction(new DefaultTransactionDefinition());
//2.调用方法
Object[] args = pjp.getArgs();
Object result = null;
try {
result = pjp.proceed(args);
} catch (Throwable throwable) {
//3.1 回滚
// throwable.printStackTrace();
System.out.println("事务出现异常,回滚");
platformTransactionManager.rollback(txStatus);
throw new RuntimeException(throwable);
}
//3.2 提交
System.out.println("事务处理完成,提交");
platformTransactionManager.commit(txStatus);
return result;
}
}
最后测试:
CourseService courseService = ctx.getBean(CourseService.class);
Course course = new Course();
course.setCourseName("Java入门");
course.setCategory("Java");
course.setPrice(10.0D);
course.setSvipPrice(10.0D);
course.setVideoType("xx");
course.setChargeType("");
course.setPurchaseCount(0);
course.setStudyCount(0);
course.setDescription("");
course.setImage("");
course.setTeacherId(0);
course.setTeacherName("");
course.setTeacherDesc("");
course.setTeacherAvatar("");
Chapter chapter = new Chapter();
chapter.setTitle("万物皆对象");
chapter.setChapterOrder(1);
List<Chapter> chapters = Arrays.asList(chapter);
courseService.addCourse(course,chapters);