Java AOP面向切面编程入门攻略
什么是AOP编程
AOP(AspectOriented Programming),即面向切面编程,是OOP编程模式的一种补充。AOP编程是通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。
在传统的OOP编程中,我们将所有重复出现的代码封装到相应的模块或类中,实现代码复用。通过继承或组合等方式,可以将这些模块或类组装成一个完整的系统。但是,当有新的需求或变化时,这些相同的代码需要在每个模块或类中进行修改,工作量非常大,不利于维护和扩展。
而AOP编程可以将横切关注点(如日志、事务等)从各个模块中分离出来,通过将这些关注点动态地织入到程序代码中来统一维护,从而实现程序功能的复用和统一维护,降低了代码的耦合性。
AOP的核心概念
切点(Pointcut)
切点是指我们要处理的目标类或方法。对于每一个切点,都会定义一个相应的切面(Aspect)。
切点可以使用类名、方法名等方式来定义。常见的切点表达式如下:
- execution:表示满足指定规则的方法执行时。例如,
execution(* com.example.service..*.*(..))
表示com.example.service包及其子包下的所有方法都符合该切点表达式。 - within:表示在满足指定规则的类型内部。例如,
within(com.example.service.*)
表示所有com.example.service包下的类及子类都符合该切点表达式。 - annotation:表示满足指定规则的注解标注的方法执行时。例如,
@annotation(org.springframework.transaction.annotation.Transactional)
表示使用了@Transactional注解的方法都符合该切点表达式。
通知(Advice)
通知是指在切点中需要执行的代码。在AOP中,一个切面包含了一个或多个通知。
通知的类型如下:
- 前置通知(Before advice):在目标方法执行前执行。
- 后置通知(After advice):在目标方法执行后执行,无论是否抛出异常,都执行。
- 返回通知(AfterReturning advice):在目标方法执行后执行,只有在方法正常完成时才执行。
- 异常通知(AfterThrowing advice):在目标方法抛出异常后执行。
- 环绕通知(Around advice):在目标方法执行前和执行后都会执行。
切面(Aspect)
切面是横切关注点的实现。它包含了一个切点和一个或多个通知。
在AOP中,我们可以开发多个切面,每个切面都拥有自己的通知,而同一个切点也可以有多个切面。
AOP开发示例1:简单的日志记录器
下面是一个简单的用于记录日志的切面。
@Aspect
@Component
public class LogAspect {
// 定义一个切点,表示com.example.service包及其子包下的所有方法
@Pointcut("execution(* com.example.service..*.*(..))")
public void serviceLog() {}
// 在目标方法执行前记录日志
@Before("serviceLog()")
public void doBefore(JoinPoint joinPoint) {
// 获取目标方法名
String methodName = joinPoint.getSignature().getName();
// 获取目标类名
String className = joinPoint.getTarget().getClass().getName();
// 构造日志消息
String logMsg = "开始执行 " + className + "." + methodName;
// 记录日志
System.out.println(logMsg);
}
// 在目标方法执行后记录日志
@AfterReturning("serviceLog()")
public void doAfterReturning(JoinPoint joinPoint) {
// 获取目标方法名
String methodName = joinPoint.getSignature().getName();
// 获取目标类名
String className = joinPoint.getTarget().getClass().getName();
// 构造日志消息
String logMsg = "执行完成 " + className + "." + methodName;
// 记录日志
System.out.println(logMsg);
}
}
在以上代码中:
- @Aspect注解表示该类是一个切面。
- @Component注解表示该类是一个Spring组件,可以被自动注入到其他组件中。
- @Pointcut注解表示定义了一个切点,即com.example.service包及其子包下的所有方法。
- @Before和@AfterReturning注解分别表示前置和后置通知,用于在目标方法执行前和执行后记录日志。
AOP开发示例2:传递参数
下面是一个用于判断用户是否有权限的切面,它传递了一个参数。
@Aspect
@Component
public class PermissionAspect {
// 定义一个切点,表示需要权限控制
@Pointcut("@annotation(com.example.annotation.Permission)")
public void permissionCheck() {}
// 在目标方法执行前进行权限判断
@Before("permissionCheck() && @annotation(permission)")
public void checkPermission(JoinPoint joinPoint, Permission permission) {
// 获取请求参数
Object[] args = joinPoint.getArgs();
if(args.length == 0) {
throw new PermissionDeniedException("请求参数为空!");
}
String userId = (String) args[0];
// 判断用户权限
if(!permission.value().contains(userId)) {
throw new PermissionDeniedException("您没有权限访问该接口!");
}
}
}
在以上代码中:
- @annotation(permission)表示获取注解中的value值,即授权列表。
- joinPoint.getArgs()方法获取目标方法的参数列表。
结束语
以上就是AOP入门攻略以及两个示例。AOP虽然能够提升代码的复用性和可维护性,但也会增加代码的复杂度,所以在使用AOP时,需要谨慎选择切点和通知的类型,以便在保证代码可读性的前提下,发挥AOP的优势。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java开发AOP面向切面编程入门 - Python技术站