@Aspect通配符
- *:匹配任意字符,只能匹配一个元素
- ..:匹配任意字符,可以匹配多个元素
- +:按类型匹配指定类的所有类,必须在类名后面,继承或者扩展指定类的所有类,也包括本身
逻辑运算符
- &&(and):与操作,切点的交集
- ||(or):或操作,切点的并集
- !(not):非操作,切点的反集
//匹配com.sunjie包下所有的get方法
@Before("within(com.sunjie.*)"+" && execution(* get(..))")
//匹配所有get方法,但是其类非User类型
@Before("!target(com.sunjie.User)"+" && execution(* get(..))")
//匹配所有User类型或者Teacher类型的类的方法
@Before("target(com.sunjie.User)"+" || target(com.sunjie.Teacher")
@Aspect增强注解
1.@Before
@Before(value=”pointcut()”)
执行方法前调用
2.@AfterReturning
@AfterReturning(value=”pointcut()”,returning=”result”)
执行方法正常返回后调用,异常不调用,
returning成员,可以将目标对象方法的返回值绑定给增强的方法
3.@Around
@Around(value=”pointcut()”)
环绕增强,唯一可以修改方法返回值的注解
4.@AfterThrowing
@AfterReturning(value=”pointcut()”,throwing =”error”)
异常抛出增强
throwing成员,可以将抛出的异常绑定到增强方法中
5.@After
@After(value=”pointcut()”)
方法执行后调用,不管异常还是正常结束,都会调用,一般用于释放资源。
5.@DeclareParents
@DeclareParents(value=”com.sunjie.User”,defaultImpl=BoySex.Class)
引介增强
@Aspect
public class UserAspect {
@DeclareParents(value="com.sunjie.User",//为这个类添加接口
defaultImpl=BoySex.class)//默认实现类
public Sex sex; //实现的接口
}
@Aspect切点表达式函数
1.方法切点函数
- execution():方法匹配模式串(支持所有通配符)
表示满足某一匹配模式的所有目标类方法连接点
execution(<修饰符> <返回类型> <方法名> <参数> <异常>)
修饰符、异常可空
例子
//匹配所有public的方法
execution(public * *(..))
//匹配所有以To结尾的方法
execution(* *To(..))
//匹配所有User类的方法,如果User为接口,则匹配所有此接口的实现类的此接口方法
execution(* com.sunjie.User.*(..))
//匹配User类型的所有类的方法
execution(* com.sunjie.User+.*(..))
//匹配所有 com.sunjie包下的所有类的所有方法
execution(* com.sunjie.*(..))
//匹配所有 com.sunjie包下以及子包下的所有类的所有方法
execution(* com.sunjie..*(..))
//匹配所有com下的任何包中类名以User结尾,get开头的方法
execution(* com..*.*User.get*(..))
//匹配所有方法名为get,第一个参数为Strng,第二个参数为int的方法
//java.lang 下的可以直接用类名,其他必须用全限定类名
execution(* get(String,int))
//匹配所有方法名为get,第一个参数为Strng,第二个参数为任意类型的方法
execution(* get(String,*))
//匹配所有方法名为get,第一个参数为Strng,后面可以是任意多个参数的任何类型的方法
execution(* get(String,..))
//匹配所有方法名为get,仅有一个参数,且为Object的类型或者子类
execution(* get(Object+))
- @annotation():方法注解类名
表示标注了特定注解的目标类方法连接点
//匹配所有标注了@MyAnno注解的方法,进行后置怎强
@AfterReturning("@annotation(com.sunjie.MyAnno)")
public void show(){
System.out.println("hello");
}
2.方法入参切点函数
- args():类名(支持+通配符)
运行入参对象的类型定义连接点
//匹配参数为Use类型的类或者子类
args(com.sunjie.User)
//区别,只匹配参数为User类型的类,不包括子类
execution(* *(com.sunjie.User))
- @args():类型注解类名
运行入参对象的类是否标注特定注解定义连接点
3.目标类切点函数
- within():类匹配串(支持所有通配符)
只能是类,接口无任何作用
//匹配User类的所有方法
within(com.sunjie.User)
//匹配com.sunjie包下的所有类的方法,不包括子包
within(com.sunjie.*)
//匹配com.sunjie包下以及子包下的所有类的方法
within(com.sunjie..*)
- target():类名(支持+通配符)
//匹配所有User类型的类的所有方法,包括未在User中定义的方法
target(com.sunjie.User)
- @within():类型注解类名
- @target():类型注解类名
命名切点
public class Cut{
切点命名,只能在本切面类中使用
@Pointcut("within(com.sunjie.User)")
private void cut1();
切点命名,只能在本切面类或者子类中使用
@Pointcut("within(com.sunjie.User)")
protected void cut2();
切点命名,可以在任何类使用
@Pointcut("within(com.sunjie.User)")
public void cut3();
切点命名,复合切点
@Pointcut("cut1() and cut2()")
public void cut4();
}
//其他类引用
@Before("Cut.cut4()")
增强执行顺序
- 在同一个切面类中的定义,则按照定义顺序来
- 在不同的切面类中定义,且实现了Ordered接口,按照序号顺序,越小越先
- 在不同切面类,且没实现Ordered接口,则不确定
连接点信息
Aspect使用JoinPoint表示连接点对象,环绕增强使用ProceedingJoinPoint,该类是JoinPoint的子类。
JoinPoint方法
- getArgs():获取入参
- getSignature():获取方法签名对象
- getTarget():获取连接点所在的目标对象
- getThis:获取代理对象本身
ProceedingJoinPoint方法
除上述方法外,多两个方法
- proceed():反射执行方法
- proceed(args):使用新参数执行方法
绑定入参
//匹配过程
//通过name,age名称查询增强方法中的参数类型,即bind(Integer age,String name)
//发现name为Sting类型,age为Integer类型
//所以匹配User类的所有第一个入参为String类型,第二个是Integer类型的方法
@Before("target(com.sunjie.User) && args(name,age)")
public void bind(Integer age,String name){
}