第三章、Spring动态代理详解
1.额外功能的详解
1.MethodBeforeAdvice分析
1.MethodBeforeAdvice接口作用:额外功能运行在原始功能执行之前,进行额外功能操作
public class Before implements MethodBeforeAdvice {
/**
* 作用: 把需要运行在原始方法执行之前运行的额外功能, 书写在 before 方法中
*
* Method: 额外功能所增加给的那个原始方法
* login
* register
* --------
* showOrder
*
* Object[]: 额外功能所增加给的那个原始方法的参数
* String name,String password
* User
* --------
*
* Object: 额外功能所增加给的那个原始对象
* UserServiceImpl
* ---------------
* OrderServiceImpl
*/
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("---new method before advice log---");
}
}
2.before方法中的3个参数在实战中,该如何使用
before方法的参数,在实战中,会根据需求进行使用,不一定都会用到,也有可能都用不到
孙哥:”我用了 15 年 Spring 一次都没有用到过这个。"
3.MethodInterceptor(方法拦截器)
MethodInterceptor接口:额外功能可以根据需要运行在原始方法执行的 前 后 前后
- 参数:MethodInvocation:额外功能所增加给的那个原始方法 (login, register)
- 返回值:Object:原始方法的返回值 (没有就返回 null)
- invocation.proceed():原始方法运行
额外功能运行原始方法执行之前
public class Around implements MethodInterceptor {
/*
invoke方法的作用:额外功能书写invoke
*/
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
System.out.println("---------log------");
Object ret = Invocation.proceed();
return ret;
}
}
额外功能运行原始方法执行之后
public class Around implements MethodInterceptor {
/*
invoke方法的作用:额外功能书写invoke
*/
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
Object ret = Invocation.proceed();
System.out.println("---------log------");
return ret;
}
}
额外功能运行原始方法执行之前 之后
什么样的额外功能 运行在原始方法执行之前 之后
事务!
public class Around implements MethodInterceptor {
/*
invoke方法的作用:额外功能书写invoke
*/
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
System.out.println("---------log------");
Object ret = Invocation.proceed();
System.out.println("---------log------");
return ret;
}
}
额外功能运行在原始方法抛出异常的时候
public class Around implements MethodInterceptor {
/*
invoke方法的作用:额外功能书写invoke
*/
@Override
public Object invoke(MethodInvocation Invocation) throws Throwable {
Object ret = null;
try {
ret = Invocation.proceed();
} catch (Throwable e) {
System.out.println("---------原始方法抛出异常 执行的额外功能---------");
e.printStackTrace();
}
return ret;
}
}
MethInterceptor影响原始方法的返回值
原始方法的返回值,直接作为invoke方法的返回值返回,MethodInterceptor不会影响原始方法的返回值
MethodInterceptor影响原始方法的返回值
invok方法的返回值,不要返回原始方法的运行结果即可
public class Around implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("---log---");
Object ret = methodInvocation.proceed();
return false;
}
}
2.切入点详解
切入点决定额外功能加入的位置(方法)
<aop:pointcut id="pc" expression="execution(* *(..))"/>
expression="execution(* *(..))--->匹配所有方法
<aop:pointcut id="pc" expression="execution(* *(..))"/>
expression="execution(* *(..))--->匹配所有方法
2.1切入点表达式
1.方法切入点表达式
1.* *(..)--->匹配所有方法
定义一个方法
public void add(int i, int j)
* * (..)
* * (..) --> 所有方法
* ---> 修饰符 返回值
* ---> 方法名
() ---> 参数表
.. ---> 对于参数没有要求 (参数有没有,参数有⼏个都行,参数是什么类型的都行)
定义login方法作为切入点
<!-- 定义login作为切入点 -->
<aop:pointcut id="pc" expression="execution(* login (..))"/><!-- 定义register作为切入点 -->
<aop:pointcut id="pc" expression="execution(* register (..))"/>
定义login方法且login方法有两字符串类型参数作为切入点
<aop:pointcut id="pc" expression="execution(* login (String,String))"/><
<!-- ⾮ java.lang 包中的类型, 必须要写全限定名 -->
<aop:pointcut id="pc" expression="execution(* register (com.yusael.proxy.User))"/><!-- ..可以和具体的参数类型连用 -->
<aop:pointcut id="pc" expression="execution(* login(String, ..))"/>
<!-- === login(String), login(String,String), login(String,com.baizhi.edu.proxy.User) -->
精准方法切入点限定
修饰符 返回值 包。类。方法(参数)
<aop:pointcut id="pc" expression="execution(* com.yusael.proxy.UserServiceImpl.login(..))"/>
<aop:pointcut id="pc" expression="execution(* com.yusael.proxy.UserServiceImpl.login(String, String))"/>
2.类切入点
指定特定的类作为切入点(额外功能加入的位置),自然这个类中的所有方法,都会加入对应的额外功能
语法1
类中所有的方法都加入了额外功能
* com.liulei.proxy.UserServiceImpl.*(..)
语法2
#忽略包
1.类只存在一级包 com.UserServiceImpl
<aop:pointcut id="pc" expression="execution(* *.UserServiceImpl.*(..))"/>2.类存在多级包 com.liulei.proxy.UserServiceImpl
<aop:pointcut id="pc" expression="execution(* *..UserServiceImpl.*(..))"/>
3.包切入点表达式(更具有实战价值)
1.指定包作为额外功能加入的位置,自然包中的所有类以及方法都会加入额外功能
语法1
#切入点包中的所有类,必须在proxy包中,不能在proxy包的子包中。
<aop:pointcut id="pc" expression="execution(* com.liulei.proxy.*.*(..))"/>
语法2
# 切入点当前包及其⼦包都生效
<aop:pointcut id="pc" expression="execution(* com.liulei.proxy..*.*(..))"/>
2.2 切入点函数
切入点函数:用于执行切入点表达式
1.execution
1.最为重要的切入点函数
2.执行了方法切入点表达式,类切入点表达式,包切入点表达式
弊端:execution执行切入点表达式,书写麻烦
注意:其他切入点的函数,简化execution书写的复杂度,功能一样
2.args
作用:主要用于函数(方法)参数的匹配
切入点:方法参数必须是2个字符串类型的参数
# 使用 execution
<aop:pointcut id="pc" expression="execution(* *(String, String))"/># 使用 args<aop:pointcut id="pc" expression="args(String, String)"/>
3.within
作用:主要用于进行类,包切入点的表达式的匹配
切入点: UserServiceImpl 这个类
# 使用 execution
<aop:pointcut id="pc" expression="expression(* *..UserServiceImpl.*(..))"/># 使用 within
<aop:pointcut id="pc" expression="within(*..UserServiceImpl)"/>
切入点: com.yusael.proxy 这个包
# 使用 execution
<aop:pointcut id="pc" expression="execution(* com.liulei.proxy..*.*(..)"/># 使用 within
<aop:pointcut id="pc" expression="within(com.liulei.proxy..*)"/>
4.@annotation
作用:为具有特殊注解的方法加入额外功能
创建注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
然后我们要为使用Log注解的方法提供额外功能
<aop:pointcut id="pc" expression="@annotation(com.liulei.Log)"/>
5.切入点函数的逻辑运算
指的是 整合多个切入点函数一起配合工作,进而完成更为复杂的需求
and与操作
5.切入点函数的逻辑运算
指的是 整合多个切入点函数一起配合工作,进而完成更为复杂的需求
and与操作
注意:与操作不能用于通知类型的切入点函数
案例:注意:与操作不同⽤于同种类型的切⼊点函数
以下这个是错误的, 因为不存在同时叫 login 和 register 的方法
<aop:pointcut id="pc" expression="execution(* login(..)) and execution(* register(..))"/>
or或操作
案例: 方法名叫 register 或 login 的⽅法作为切⼊点
<aop:pointcut id="pc" expression="execution(* login(..)) or execution(* register(..))"/>
第四章、AOP编程
1. AOP概念
AOP(Aspect Oriented Programing) 面向切面编程 Spring动态代理开发
以切面为基本单位的开发,通过切面间的彼此协调,相互调用,完成程序的创建
切面 = 切入点 + 额外功能/
OOP(Object Oriented Programing) 面向对象编程 Java
以对象为基本单位的程序开发,通过对象间得彼此协同,相互调用,完成程序构建
POP(Producer Oriented Programing)面向过程(方法,函数)编程
以过程为基本单位的程序开发,通过过程间彼此协调,相互调用,完成程序构建
AOP概念
本质就是Spring的动态代理开发,通过代理类为原始类增加额外功能
好处:有利于原始类的维护
注意:AOP编程不可能取代OOP,是OOP编程的补充
2. AOP编程的开发步骤
1.原始对象
2.额外功能(MethodInterceptor)
3.切入点
4.组装切面(额外功能+切入点)
3.切面的名词解释
切面 = 切入点 + 额外功能
几何学
面 = 点+ 相同的性质