本文已收录于【Spring源码札记专栏】。
关联文章:
(二)Spring AOP源码-1.概述与设计原理-01概述
(二)Spring AOP源码-1.概述与设计原理-02设计原理
什么是AOP?
AOP(Aspect Oriented Programming),即面向切面编程,有种说法是对面向对象编程(OOP)的补充和完善。我们知道OOP允许开发者定义纵向的关系,但并不适合定义横向的关系。比如当需要为多个不具备继承关系的类添加一个公共行为,例如日志功能,只有在每个类中都引入日志等行为。这样就导致程序中存在大量重读代码。
AOP将公共行为封装成切面(Aspect)。所谓切面,简单说就是将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
基本概念
- 横切关注点(crosscutting concern):对哪些方法进行拦截,拦截后怎么处理。
- 切面(Aspect):切面是对横切关注点的抽象。
- 连接点(JoinPoint):被拦截到的点。因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法。
- 切入点(Pointcut):连接点的集合。通常是一个表达式,用于确定哪些类的哪些函数需要插入横切逻辑。
- 通知(Advice):具体的横切逻辑。Spring中有四种Advice:
- 前置通知(Before Advice)
- 后置通知(After Advice)
- 返回通知(After Return Advice)
- 环绕通知(Around Advice)
- 抛出异常后通知(After Throwing Advice)
- AOP代理:AOP框架创建的对象,代理就是目标对象的加强。
- 织入(weave):将切面应用到目标对象并导致代理对象创建的过程。
- 引入(introduction):在运行期为类动态地添加一些方法或字段。
Spring AOP示例
业务类
@Service
public class HelloWorld {
public void sayHello() {
System.out.println("Hello, World!");
}
}
切面类
@Component
@Aspect
public class AspectDemo {
@Pointcut("execution(* aopdemo..*.*(..))")
public void pointCut() {
}
@Before("pointCut()")
public void doBefore(JoinPoint joinPoint) {
System.out.println("AOP Before Advice...");
}
@After("pointCut()")
public void doAfter(JoinPoint joinPoint) {
System.out.println("AOP After Advice...");
}
@AfterReturning(pointcut = "pointCut()", returning = "returnVal")
public void afterReturn(JoinPoint joinPoint, Object returnVal) {
System.out.println("AOP AfterReturning Advice:" + returnVal);
}
@AfterThrowing(pointcut = "pointCut()", throwing = "error")
public void afterThrowing(JoinPoint joinPoint, Throwable error) {
System.out.println("AOP AfterThrowing Advice..." + error);
System.out.println("AfterThrowing...");
}
@Around("pointCut()")
public void around(ProceedingJoinPoint pjp) {
System.out.println("AOP Aronud before...");
try {
pjp.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
System.out.println("AOP Aronud after...");
}
}
配置文件
<?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:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="aopdemo" />
<aop:aspectj-autoproxy />
</beans>
测试
public class AspectTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
HelloWorld hw = (HelloWorld) ctx.getBean("helloWorld");
hw.sayHello();
}
}
AOP使用场景
AOP作为面向对象的补充,广泛应用于提供一些具有横切性质的功能,比如权限控制、异常处理、事务管理、日志记录、数据校验等等。