前面2篇主要介绍了组件注册相关的东西,接下来主要介绍AOP相关的,AOP主要用于日记记录,事务处理,参数校验等方面。下面这个demo就以日志记录为例。
一、新建maven工程,添加依赖,下面是我的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qxf</groupId>
<artifactId>spring-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
二、AOP实现
1.新建业务类Caculator
package com.qxf.aop;
import org.springframework.stereotype.Component;
/**
* @Auther: qiuxinfa
* @Date: 2019/12/15
* @Description: com.qxf.aop
*/
@Component
public class Caculator {
public Caculator(){
System.out.println("Caculator...构造器");
}
public double div(Integer a,Integer b){
System.out.println("执行: "+a+" / "+b);
return a/b;
}
}
2.新建一个切面类LogAspect
package com.qxf.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* @Auther: qiuxinfa
* @Date: 2019/12/15
* @Description: 日志切面类
*/
@Aspect
@Component
public class LogAspect {
//切点:
// @Pointcut("execution(public double com.qxf.aop.Caculator.div(double ,double ))")
//第一个*:表示任意修饰符任意返回值
//第二个*:表示任意方法
//参数列表中的2个点:表示任意参数
@Pointcut("execution(* com.qxf.aop.Caculator.*(..))")
public void myPointcut(){
}
//执行目标方法之前执行该方法
@Before("myPointcut()")
public void logStart(JoinPoint joinPoint){
System.out.print(joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName()
+"()方法开始执行,参数为:");
for (Object obj : joinPoint.getArgs()){
System.out.print(obj.toString()+"\t");
}
System.out.println();
}
//执行目标方法之后执行,不管是否发生异常,都会执行该方法
@After("myPointcut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName()
+"()方法执行结束");
}
//方法正常执行之后执行
//JoinPoint只能是参数列表的第一个
@AfterReturning(value = "myPointcut()",returning = "obj")
public void logReturing(JoinPoint joinPoint,Object obj){
System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName()
+"()方法的返回值为-->"+obj);
}
//方法发生异常执行
//JoinPoint只能是参数列表的第一个
@AfterThrowing(value = "myPointcut()",throwing = "e")
public void logException(JoinPoint joinPoint,Exception e){
System.out.println(joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName()
+"()方法发生异常:"+e.getMessage());
}
}
3.配置类
package com.qxf.config;
import com.qxf.aop.Caculator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @Auther: qiuxinfa
* @Date: 2019/12/15
* @Description: spring中aop配置
*/
@Configuration
@ComponentScan("com.qxf.aop")
@EnableAspectJAutoProxy //开启自动代理,否则aop不起作用
public class AOPConfig {
}
4.测试类
package com.qxf.test;
import com.qxf.aop.Caculator;
import com.qxf.config.AOPConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Auther: qiuxinfa
* @Date: 2019/12/15
* @Description: com.qxf.test
*/
public class AOPConfigTest {
@Test
public void testAOP(){
ApplicationContext context = new AnnotationConfigApplicationContext(AOPConfig.class);
Caculator caculator = context.getBean(Caculator.class);
caculator.div(9,2);
}
}
5.测试结果
(1)正常执行时
(2)发生异常时
对于AOP的理解,可以结合try-catch-finally代码块来理解,大体上是下面这个流程
try{
执行前置通知@Before
执行目标方法
执行返回通知(如果有返回值的话)@AfterReturning
}catch(Exception e){
执行异常通知@AfterThrowing
}finally{
执行最终通知@After
}