- 额外功能的详解
1.1 MethodBeforeAdvice接口分析
- 该接口作用:额外功能运行在原始方法执行之前,进行额外操作
public class Before implements MethodBeforeAdvice {/*作用:需要把运行在原始方法之前执行的额外功能书写在before方法中Method:额外功能所增加给的的原始方法Object[]:额外功能所增加给的那个原始方法的参数Object:额外功能所增加给的那个原始对象*/@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("Before.before");}}
- before方法的三个参数在实战中如何使用?- before方法的三个参数在实战中根据需要选择使用,不一定都用,也可能都不用
1.2 MethodInterceptor(方法拦截器)
- MethodBeforeAdvice执行在原始方法执行之前,而MethodInterceptor在原始方法执行之前、之后或前后执行
public class Around implements MethodInterceptor {/** invoke方法的作用:额外功能书写在invoke中* 额外功能可以根据需要执行在原始方法执行之前或之后* 确定:原始方法如何运行* 参数:MethodInvocation Method:原始方法所附加给的那个方法* invocation.proceed()代表原始方法运行* 返回值:原始方法执行后的返回值(原始方法返回值)* */@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("--------Around.before.log--------");//运行在原始方法执行之前Object ret = invocation.proceed(); //原始方法执行System.out.println("--------Around.after.log--------"); //运行在原始方法执行之后return ret;}}
- 额外功能运行在原始方法执行之前
@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("--------Around.before.log--------");//运行在原始方法执行之前Object ret = invocation.proceed(); //原始方法执行return ret;}
- 额外功能运行在原始方法执行之后
@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {Object ret = invocation.proceed(); //原始方法执行System.out.println("--------Around.after.log--------"); //运行在原始方法执行之后return ret;}
- 额外功能运行在原始方法执行之前、之后
@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("--------Around.before.log--------");//运行在原始方法执行之前Object ret = invocation.proceed(); //原始方法执行System.out.println("--------Around.after.log--------"); //运行在原始方法执行之后return ret;}
- 额外方法运行在原始方法抛出异常时
@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {Object ret = null;try {ret = invocation.proceed();} catch (Throwable throwable) {System.out.println("--------Around.Exception.log---------");throwable.printStackTrace();}return ret;}
- MethodInterceptor方法可以影响原始方法的返回值- 原始方法的返回值直接作为invoke方法的返回值,不会影响原始方法的返回值- 原始方法的返回值不直接作为invoke方法的返回值,则会影响原始方法的返回值
- 切入点详解
切入点决定额外功能加入的位置(方法)<aop:pointcut id="pc" expression="execution(* *(..))" />
其中:execution( (..)) 匹配了所有方法
- execution() 切入点函数
- *(..) 切入点表达式
2.1 切入点表达式
方法切入点
- 定义一个方法: public void add(int a,int b);
表达式: (..)
其中:第一个 代表 修饰符与返回值
第二个 代表 方法名
() 代表 参数表
.. 代表对参数没有要求 (对类型没有要求,对数量没有要求)
- 定义login方法作为切入点:方法定义: `public boolean login(String name,String password);`<br /> 表达式: `* login(..)`- 定义login方法为切入点且login方法有两个字符串类型的形参:
方法定义: public boolean login(String name,String password);
表达式: * login(String,String)
注意:
1. 非java.lang包中的类型,必须写全限定名1. `..`可以与具体的参数类型连用,如`* ``login(String,..)`表达式表示第一个参数为String类型,其余参数随意- 精准方法切入点限定
修饰符 返回值 包.类.方法(参数)
(..)
- 类切入点
- 定义:指定特定类作为切入点(额外功能加入的位置),自然这个类中的所有方法加入额外功能
- 语法1:类中所有方法都加入额外功能
* com.baizhi.proxy.UserServiceImpl.*(..)
- 语法2:忽略包
情况一:类只存在于一级包,如com.UserServiceImpl* *.UserServiceImpl.*(..)
情况二:类存在于多级包,如com.baizhi.proxy.UserServiceImpl* *..UserServiceImpl.*(..)
- 包切入点表达式
- 定义:指定包作为切入点的位置,自然这个包中的所有类的所有方法都加入额外功能
- 语法一:切入点包中的所有类都必须在proxy包中,而不能在其子包中
* com.baizhi.proxy.*.*(..)
- 语法二:切入点包中的所有类在proxy包或其子包中
* com.baizhi.proxy..*.*(..)
2.2 切入点函数
切入点函数:用于执行切入点表达式
- execution
- 最为重要的切入点表达式,功能最全
- 执行:方法切入点表达式、类切入点表达式、包切入点表达式
- 弊端:execution执行表达式时,书写比较麻烦
- 注意:其他函数仅仅为了简化execution书写表达式,功能是一样的
- args
- 作用:主要用于函数(方法)参数匹配
- 切入点:方法的参数必须是两个字符串类型
- 表达式:args(String,String)
- within
- 作用:主要用于类、包切入点表达式匹配
- 切入点:类或包
- within(*..类名)
- within(包名..*)
- @annotation
- 为具有特殊注解的方法加入额外功能
<aop:pointcut id=" " expression="@annotation(注解的全限定名)" />
- 切入点函数的逻辑运算
- 作用:整合多个切入点函数一起配合工作,以实现更为复杂的功能
- and(与)操作:同时操作(同时满足)
- 例:execution( login(String,String))——> execution( login(..)) and args(String,String)
- 注意:与操作不能用于同种类型的切入点函数
- or(或)操作:
- 例:execution( login(..)) or execution( register(..))
- 总结
