概述
本文通过案例讲解:@Aspect、@Before、@After、@AfterReturning、 @AfterThrowing 注解的作用
尤其是:@Before、@After、@AfterReturning、 @AfterThrowing 注解的执行顺序
案例
使用注解的方式实现aop,实现 不修改 UserSrvImpl 源代码的情况下,增加打印日志的功能
工程目录
创建maven工程
略
修改pom.xml
添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
注解需要依赖 aspectjweaver
定义service接口
spring默认使用JDK动态代理实现 aop,所以需要接口
public interface IUserService {
public void save(String username, String password);
public int update();
public int delete(String id);
}
service实现类
@Service
public class UserSrvImpl implements IUserService {
public UserSrvImpl(){
System.out.println("UserSrvImpl构造方法");
}
public void save(String username,String password){
// System.out.println("UserSrvImpl保存 报错");
// int i=1/0;
System.out.println("UserSrvImpl保存 "+username+"-"+password);
}
public int update(){
System.out.println("UserSrvImpl修改 ");
return 1;
}
public int delete(String id){
System.out.println("UserSrvImpl删除 "+id);
return 2;
}
}
实现Logger日志类
//由spring容器管理,该类不属于Controller、Service、Repository,所以用@Component注解
@Component
//表明该类为切面类
@Aspect
public class Logger {
/*
在 com.yingqi.service 包下的类 的 方法,都能注入代码
*/
@Pointcut("execution(* top.malaoshi.service.*.*(..))")
public void pt(){
}
/*
在 com.yingqi.service 包下的类 的 方法,执行之前 会先执行下面方法
*/
@Before("pt()")
public void beforePrint(JoinPoint jp){
Signature s=jp.getSignature();
System.out.println("=======before:::"+"调用 " + s.getDeclaringTypeName()+"."+s.getName() + ",参数:"
+ Arrays.toString(jp.getArgs()));
}
/*
在 com.yingqi.service 包下的类 的 方法,执行之后(不论是否抛异常) 会执行下面方法
*/
@After("pt()")
public void afterPrint(){
System.out.println("======after");
}
/*
在 com.yingqi.service 包下的类 的 方法,执行之后(没抛异常) 会执行下面方法
*/
@AfterReturning(pointcut="pt()",returning="result")
public void afterReturningPrint(JoinPoint jp, Object result){
Signature s=jp.getSignature();
System.out.println("======afterReturning:::"+"调用 " + s.getDeclaringTypeName()+"."+s.getName() + " ,返回值:" + result);
}
/*
在 com.yingqi.service 包下的类 的 方法,执行之后(抛异常了) 会执行下面方法
*/
@AfterThrowing(pointcut="pt()",throwing="e")
public void afterThrowingPrint(JoinPoint jp, Exception e){
Signature s=jp.getSignature();
System.out.println("======afterThrowingPrint:::"+s.getDeclaringTypeName()+"."+s.getName() + ",抛出异常:" + e);
}
}
配置类
@Configuration
@ComponentScan("top.malaoshi")
//启用aop注解
@EnableAspectJAutoProxy
public class ApplicationConfig {
}
注意
必须 加上 @EnableAspectJAutoProxy 注解,才能开启aop,解释参见:
https://www.malaoshi.top/show_1IXUetDK7Ji.html
测试-执行成功
主启动类
public class Main {
public static void main(String[] args) {
ApplicationContext ac=new AnnotationConfigApplicationContext(ApplicationConfig.class);
IUserService srv=(IUserService)ac.getBean("userSrvImpl");
srv.save("李雷","123456");
}
}
执行成功的通知顺序:
- before
- 目标方法
- after
- afterReturning
测试-执行报错
修改 UserSrvImpl
让 save() 方法抛出异常
@Service
public class UserSrvImpl implements IUserService {
public UserSrvImpl(){
System.out.println("UserSrvImpl构造方法");
}
public void save(String username,String password){
System.out.println("UserSrvImpl保存 报错");
int i=1/0;
// System.out.println("UserSrvImpl保存 "+username+"-"+password);
}
public int update(){
System.out.println("UserSrvImpl修改 ");
return 1;
}
public int delete(String id){
System.out.println("UserSrvImpl删除 "+id);
return 2;
}
}
执行报错的通知顺序:
- before
- 目标方法
- after
- afterThrowingPrint
