今天学习了AOP,记录一下自己的理解了。
AOP基础概念
- (1)Aspect(切面):通常是一个类,里面可以定义切入点和通知
- (2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用
- (3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around
- (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
- (5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
AOP通知
- 前置通知:在我们执行目标方法之前运行(@Before)
- 后置通知:在我们目标方法运行结束之后 ,不管有没有异常(@After)
- 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
- 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
简单了解之后,开始练习一下吧。
一、导入jar包
我用的是maven工程
<?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>org.example</groupId>
<artifactId>aop01</artifactId>
<version>1.0-SNAPSHOT</version>
<!--spring-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!--AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
</dependencies>
</project>
二、开启spring包扫描和切面注解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--包扫描-->
<context:component-scan base-package="com.aaa.after"/>
<!--开启切面注解-->
<mvc:aspectj-autoproxy/>
</beans>
三、创建ArithmeticCalculator接口
public interface ArithmeticCalculator {
/**
* 加法运算
* @param a
* @param b
* @return
*/
public int add(int a,int b);
/**
* 减法运算
* @param a
* @param b
* @return
*/
public int sub(int a,int b);
/**
* 乘法运算
* @param a
* @param b
* @return
*/
public int mul(int a,int b);
/**
* 除法运算
* @param a
* @param b
* @return
*/
public int div(int a,int b);
}
四、创建ArithmeticCalculatorImpl实现类
@Component //泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
@Override
public int add(int a, int b) {
int c=a+b;
return c;
}
@Override
public int sub(int a, int b) {
int c=a-b;
return c;
}
@Override
public int mul(int a, int b) {
int c=a*b;
return c;
}
@Override
public int div(int a, int b) {
int c=a/b;
return c;
}
}
五、创建切面类(通知)
@Component
@Aspect //表示该类为切面类 ----
public class LogAspect {
@Before(value = "execution(* com.aaa.after.*.*(..))") //前置通知 只要调用就会输出传入的值
public void before(JoinPoint joinPoint){//joinpoint 切点
String name = joinPoint.getSignature().getName();
Object[] args = joinPoint.getArgs();
System.out.println("AAA--->The "+name+" method begin with ["+ Arrays.asList(args) +"]");
}
@After(value = "execution(* com.aaa.after.*.*(..))") //后置通知 类似于finally
public void after(JoinPoint joinPoint){//joinpoint 切点
System.out.println("该方法总会被执行 ");
}
@AfterReturning(value = "execution(* com.aaa.after.*.*(..))",returning = "r") //后置返回通知,可以得到返回结果
public void afterReturning(int r){
System.out.println("结果"+r);
}
@AfterThrowing(value = "execution(* com.aaa.after.*.*(..))",throwing = "e") //catch 异常通知 只有发生异常时会被调用
public void afterThrowing(Exception e){
System.out.println(e.getMessage());
}
}
六、创建测试类
public class Test01 {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("application.xml");
ArithmeticCalculator impl = (ArithmeticCalculator) app.getBean("arithmeticCalculatorImpl");
int result = impl.div(10, 2);
System.out.println(result);
}
}