GitHub地址:https://github.com/binlian/binglian-AOP
AOP是什么?
1.一种编程范式,不是编程语言
2.解决特定问题,不是解决所有问题
3.OOP的补充,不是替代
AOP初衷
代码重复性
水平分离:展示层->服务处->持久层
垂直分离:模块划分(订单、库存等)
切面分离:分离功能性需求与非功能性需求
使用AOP的好处
集中处理某一关注点/横切逻辑
可以很方便地添加/删除关注点
侵入性少,增强代码可读性及可维护性
aop应用场景,权限控制,缓存控制,事务控制,审计日志,性能监控,分布式追踪,异常处理
@Aspect要切面的类的注解 配置
@Pointcut 切入选择那个类。方法或者其他进行切入
@Advice 切面时间 在什么时段进行 之前还是之后
advice 有五种
切面表达式
designators指示器
wildcards通配符 *匹配任意数量的字符、+匹配指定类及其子类、..一般用于匹配任意的子包或参数
Operators运算符 &&与操作符、||或操作符、!非操作符
三种配合使用
匹配方法
那个包下的犯法
//匹配任何公共方法
@Pointcut("execution(public * com.binglian.service.*.*(..))")
//匹配com.binglian包及子包下Service类中无参方法
@Pointcut("execution(* com.binglian..*Service.*())")
//匹配com.binglian包及子包下Service类中的任何只有一个参数的方法
@Pointcut("execution(* com.binglian..*Service.*(*))")
//匹配com.binglian包及子包下任何类的任何方法
@Pointcut("execution(* com.binglian..*.*(..))")
//匹配com.binglian包及子包下返回值为String的任何方法
@Pointcut("execution(String com.binglian..*.*(..))")
//匹配异常
execution(public * com.binglian.service.*.*(..) throws java.lang.IllegalAccessException)
//例子
@Pointcut("execution(public * com.binglian.service..*Service.*(..) throws java.lang.IllegalAccessException)")
public void matchCondition(){}
@Before("matchCondition()")
public void before(){
System.out.println("");
System.out.println("###before");
}
它拦截的是有抛出异常的方法,就是匹配异常
在异常方法之前输出###before
匹配包
within匹配那个报下的方法
//匹配ProductService类里头的所有方法
@Pointcut("within(com.binglian.service.ProductService)")
//匹配com.imooc包及子包下所有类的方法
@Pointcut("within(com.binglian..*)")
匹配注解
com.binglian.anno.AdminOnly 这个是自定义的注解 然后找到那个包所有犯法进行匹配
//匹配方法标注有AdminOnly的注解的方法
@Pointcut("@annotation(com.binglian.anno.AdminOnly) && within(com.binglian..*)")
//匹配标注有NeedSecured的类底下的方法 //class级别
@Pointcut("@within(com.binglian.anno.NeedSecured) && within(com.binglian..*)")
//匹配标注有NeedSecured的类及其子类的方法 //runtime级别
在spring context的环境下,二者没有区别
@Pointcut("@target(com.binglian.anno.NeedSecured) && within(com.binglian..*)")
//匹配传入的参数类标注有Repository注解的方法
@Pointcut("@args(com.binglian.anno.NeedSecured) && within(com.binglian..*)")
@Pointcut("@annotation(com.binglian.anno.NeedSecured) && within(com.binglian..*)")
public void matchAnno(){}
@Before("matchAnno()")
public void before(){
System.out.println("");
System.out.println("###before");
}
匹配参数
匹配方法里的参数
args相对于execution简单多了
匹配任何以find开头而且只有一个Long参数的方法
@Pointcut("execution(* *..find*(Long))")
匹配任何以find开头的而且第一个参数为Long型的方法
@Pointcut("execution(* *..find*(Long,...))")
匹配任何只有一个Long参数的方法
@Pointcut("args(Long) && within(com.binglian..*)")
匹配第一个参数为Long型的方法
@Pointcut("args(Long,..) && within(com.binglian..*)")
匹配的对象
this 拦截
target 不拦截
bean 是所有的方法
//匹配AOP对象的目标对象为指定类型的方法,即LogService的aop代理对象的方法
@Pointcut("this(com.imooc.log.Loggable)")
//匹配实现Loggable接口的目标对象(而不是aop代理后的对象)的方法
@Pointcut("target(com.imooc.log.Loggable)")
//this 可以拦截 DeclareParents(Introduction)
//target 不拦截 DeclareParents(Introduction)
//匹配所有以Service结尾的bean里头的方法
@Pointcut("bean(*Service)")
Advice注解
package com.binglian.config;
import static org.hamcrest.CoreMatchers.nullValue;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class AdviceAspectConfig {
@Pointcut("@annotation(com.binglian.anno.AdminOnly) && within(com.binglian..*)")
public void matchAnno(){}
@Pointcut("execution(* *..find*(Long)) && within(com.binglian..*)")
public void matchLongArg(){}
@Pointcut("execution(public * com.binglian.service..*Service.*(..) throws java.lang.IllegalAccessException) && within(com.binglian..*)")
public void matchException(){}
@Pointcut("execution(String com.binglian..*.*(..)) && within(com.binglian..*)")
public void matchReturn(){}
/************advice**************/
// @After("matchAnno()")
// public void after(){
// System.out.println("###after");
// }
// @AfterThrowing("matchException()")
// public void after(){
// System.out.println("###after");
// }
// @AfterReturning(value="matchReturn",returning="result")
// public void after(Object result){
// System.out.println("###after returning"+result);
// }
@Around("matchAnno()")
public Object after(ProceedingJoinPoint joinPoint){
System.out.println("###before");
Object result=null;
try{
result=joinPoint.proceed();
}catch (Throwable e){
System.out.println("###ex");
}finally{
System.out.println("###finally");
}
return result;
}
}