Spring AOP注解

@Aspect通配符

  1. *:匹配任意字符,只能匹配一个元素
  2. ..:匹配任意字符,可以匹配多个元素
  3. +:按类型匹配指定类的所有类,必须在类名后面,继承或者扩展指定类的所有类,也包括本身

逻辑运算符

  1. &&(and):与操作,切点的交集
  2. ||(or):或操作,切点的并集
  3. !(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(* getObject+))

  • @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()"

增强执行顺序

  1. 在同一个切面类中的定义,则按照定义顺序来
  2. 在不同的切面类中定义,且实现了Ordered接口,按照序号顺序,越小越先
  3. 在不同切面类,且没实现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){

}
发布了15 篇原创文章 · 获赞 5 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章