目录
- 前言
- 编程范式主要有以下几类
- aop 注解
- 用法
前言
spring 提供两个核心功能,一个是 Ioc(控制反转),另一个是 Aop(面向切面编程),Ioc 有助于应用对象之间的解耦,AOP 则可以实现横切关注点(如日志、安全、缓存、重复提交和事务管理)与他们所影响的对象之间的解耦。
编程范式主要有以下几类
- AOP(Aspect Oriented Programming)面向切面编程
- OOP(Object Oriented Programming)面向对象编程
- POP(procedure oriented programming)面向过程编程
- FP(Functional Programming)面向函数编程
aop 注解
AOP 主要包含了通知、切点和连接点灯术语,介绍如下:
- 通知(Advice)
通知定义了切面是什么以及何时被调用,何时调用包含以下几种:
- Before 在方法被调用之前调用通知
- After 在方法完成之后调用通知,无论方法执行是否成功
- After-returning 在方法成功执行之后调用通知
- After-throwing 在方法抛出异常后调用通知
- Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为
- 切点(PointCut)
通知定义了切面是什么和何时被调用,切点定义了何处被调用,切点的定义会匹配通知所要织入的一个或多个连接点,我们通常使用明确的类的方法名称来指定这些切点,或是利用正则表达式定义匹配的类和方法名称来指定这些切点。
- 连接点(JoinPoint)
连接点是在应用执行过程中能够插入切面的一个点,这个点可以是调用方法时,抛出异常时,甚至是修改一个字段时,切面代码可以利用这些连接点插入到应用的正常流程中,并添加新的行为,如日志、安全、事务、缓存等。
-
@Aspect
: 切面,由通知和切入点共同组成,这个注解标注在类上表示为一个切面。 -
@Joinpoint
: 连接点,被 AOP 拦截的类或者方法,在前置通知中有介绍使用@Joinpoint
获取类名、方法、请求参数。 -
Advice
: 通知的几种类型 -
@Before
: 前置通知,在某切入点@Pointcut
之前的通知 -
@After
: 后置通知,在某切入点@Pointcut
之后的通知无论成功或者异常。 -
@AfterReturning
: 返回后通知,方法执行 return 之后,可以对返回的数据做加工处理。 -
@Around
: 环绕通知,在方法的调用前、后执行。 -
@AfterThrowing
: 抛出异常通知,程序出错跑出异常会执行该通知方法。 -
@Pointcut
: 切入点,从哪里开始。例如从某个包开始或者某个包下的某个类等。
用法
AOP 在 spring 中有两种配置方式,一是 xml 配置的方式,二是自动注解的模式。
自动注解 AOP
声明切面类,包含注解 @Aspect 以及何时执行通知(Advice)
package com.ganji.demo.service.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Service;
/**
* Created by admin on 2015/9/2.
*/
@Aspect
@Service
public class XmlAopDemoUserLog {
// 配置切点 及要传的参数
@Pointcut("execution(* com.ganji.demo.service.user.UserService.GetDemoUser(..)) && args(id)")
public void pointCut(int id)
{ }
// 配置连接点 方法开始执行时通知
@Before("pointCut(id)")
public void beforeLog(int id) {System.out.println("开始执行前置通知 日志记录:"+id);
}
// 方法执行完后通知
@After("pointCut(id)")
public void afterLog(int id) {System.out.println("开始执行后置通知 日志记录:"+id);
}
// 执行成功后通知
@AfterReturning("pointCut(id)")
public void afterReturningLog(int id) {System.out.println("方法成功执行后通知 日志记录:"+id);
}
// 抛出异常后通知
@AfterThrowing("pointCut(id)")
public void afterThrowingLog(int id) {System.out.println("方法抛出异常后执行通知 日志记录"+id);
}
// 环绕通知
@Around("pointCut(id)")
public Object aroundLog(ProceedingJoinPoint joinpoint,int id) {
Object result = null;
try {System.out.println("环绕通知开始 日志记录"+id);
long start = System.currentTimeMillis();
// 有返回参数 则需返回值
result = joinpoint.proceed();
long end = System.currentTimeMillis();
System.out.println("总共执行时长" + (end - start) + "毫秒");
System.out.println("环绕通知结束 日志记录");
} catch (Throwable t) {System.out.println("出现错误");
}
return result;
}
}
以上即实现 aop。