一、概述
Spring框架的特点之一,AOP(Aspect-Oriented Programming)面向切面编程,这个切面也就是我们从一些类中得出的公用的程序,把这个公用程序拿出来作为一个切面类,当我们在业务层调用业务方法的时候,根据切点的位置来调用切面类里的方法。这样的思想可以使得我们的业务逻辑更加清晰简洁,代码也更利于维护。
二、AOP的术语
1、切面(Aspect)
横切关注点被模块化的特殊对象,即公用功能的类,用@Aspect注解标记的类。
2、通知(Advice)
切面必须要完成的工作,即在切面类中被@Before、@After等注解标记的方法。
3、目标(target)
被通知的对象,即要使用这个切面通知的类,可以通过JoinPoint.getTarget()方法来获取。
4、代理(Proxy)
向目标对象应用通知之后创建的代理对象,可以通过JoinPoint.getThis()方法来获取。
5、连接点(Joinpoint)
程序执行的某个特定的位置,比如在业务方法执行之前、业务方法执行之后、抛出异常之后,连接点由两个信息确定:方法表示的程序执行点和相对点表示的方位,可以通过通知方法的参数 JoinPoint 来获取。
6、切点(pointcut)
每个类有多个连接点,AOP通过切点定位到特定的连接点,连接点相当于数据库里的记录,切点相当于查询条件,一个切点可以匹配多个连接点,切点即通过切点表达式匹配到的方法。
三、通知
1、@Before:前置通知,在业务方法执行之前执行。
2、@After:后置通知,在业务方法执行之后执行。
3、@AfterReturning:返回通知,在业务方法执行返回结果之后执行。
4、@AfterThrowing:异常通知,在业务方法抛出异常之后通知。
5、@Around:环绕通知,围绕着业务方法执行。
四、示例
接口
package com.etime02;
public interface Operation {
public double oper(double num1, double num2);
接实现类
package com.etime02;
import org.springframework.stereotype.Component;
@Component
public class Add implements Operation{
@Override
public double oper(double num1, double num2) {
double rst = num1 + num2;
System.out.println(rst);
return rst;
}
}
切面类
package com.etime02;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
@Aspect
public class OpeAspect {
@Before("execution(* Add.oper(..))")
public void before(JoinPoint point){
System.out.println("被通知的对象名称: " +point.getTarget().getClass().toString());
System.out.println("指定的方法名称: "+point.getSignature().getName());
System.out.println("方法的参数: "+ Arrays.toString(point.getArgs()));
System.out.println("执行之前需要执行的内容");
}
@After("execution(* *.oper(..)) ")
public void after(){
System.out.println("执行之后……");
}
@AfterReturning(pointcut="execution(* *.oper(..))",returning="obj")
public void returning(JoinPoint point,Object obj){
System.out.println("返回通知.....方法返回值为:"+obj);
}
}
测试
package com.etime02;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aspectConfig.xml");
Operation add = (Operation) applicationContext.getBean("add");
double result = add.oper(1, 2);
}
}
xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!-- 开启扫描-->
<context:component-scan base-package="com.etime02">
</context:component-scan>
<!-- 开启切面-->
<aop:aspectj-autoproxy> </aop:aspectj-autoproxy>
</beans>