在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP指的是一种编程思想,是OOP的补充和完善,这篇博客里主要介绍 Spring @Aspect注解的使用。
AOP的常用术语
连接点(Joinpoint):增强程序执行的某个特定位置(要在哪个地方做增强操作)。Spring仅支持方法的连接点,既仅能在方法调用前,方法调用后,方法抛出异常时等这些程序执行点进行织入增强。
切点(Pointcut):切点是一组连接点的集合。AOP通过“切点”定位特定的连接点。通过数据库查询的概念来理解切点和连接点的关系再适合不过了:连接点相当于数据库中的记录,而切点相当于查询条件。
增强(Advice):增强是织入到目标类连接点上的一段程序代码。表示要在连接点上做的操作。
切面(Aspect):切面由切点和增强(引介)组成(可以包含多个切点和多个增强),它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的链接点中。
相关注解简介
基于连接点的方式
1、定义切面类@Aspect
@Aspect // 声明这是切面类
@Component // 注册到spring容器中
public class LogAspect {
/**
* @Pointcut() 定义切点&切点范围
*/
@Pointcut("execution(* com.practice.AspectPractice.AspectDemo.printHello(...))")
public void logPointcut() {
}
/**
* @Before 前置增强
*/
@Before("logPointcut()")
public void before(JoinPoint point) {
System.out.println(point.getTarget());
System.out.println("前置增强");
}
/**
* @Around 环绕增强
*/
@Around("logPointcut()")
public void around(ProceedingJoinPoint joinPoint) {
try {
System.out.println("环绕增强-执行切点前");
joinPoint.proceed();
System.out.println("环绕增强-执行切点后");
} catch (Throwable t) {
System.out.println("抛出异常");
System.out.println(t);
}
}
}
2、编写被增强的类
上面的execution内是一个正则表达式,“ * ” 星号表示任意返回类型的方法 ," .. "表示任意参数个数。
package com.practice.AspectPractice;
import org.springframework.stereotype.Service;
@Service
public class AspectDemo {
// 可以看到这里方法的路径,是上面切面类切点定义的范围中
public void printHello() {
System.out.println("hello,这里是pointcut");
}
}
3、编写测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class AspectDemoTest extends TestCase {
@Autowired
private AspectDemo aspectDemo;
@Test
public void test(){
aspectDemo.printHello();
}
}
结果可以看到,在执行切点前后有增强效果!
环绕增强-执行切点前
com.practice.AspectPractice.AspectDemo@18a645fd
前置增强
hello,我是被aop的方法,printHello
环绕增强-执行切点后
基于自定义注解的方式
1、定义自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
2、定义@Aspect切面,不过此时在切点上把连接点,改成自定义注解
/**
* @Pointcut() 定义切点&切点范围
*/
@Pointcut("@annotation(MyAnnotation)")
public void logPointcut() {
}
3、添加注解:在要被增强的方法前添加注解,即可起到增强效果
@Service
public class AspectDemo {
@MyAnnotation
public void printHello() {
System.out.println("hello,这里是pointcut");
}
}
参考博客