AOP 关键术语
1.target:目标类,需要被代理的类。例如:UserService
2.Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法。例如:所有的方法
3.PointCut 切入点:已经被增强的连接点。例如:addUser()
4.advice 通知/增强,增强代码。例如:after、before
5. Weaving(织入):是指把增强advice应用到目标对象target来创建新的代理对象proxy的 过程.
6.proxy 代理类:通知+切入点
7. Aspect(切面): 是切入点pointcut和通知advice的结合
具体可以根据下面这张图来理解:
AOP 的通知类型
Spring按照通知Advice在目标类方法的连接点位置,可以分为5类
前置通知
org.springframework.aop.MethodBeforeAdvice
在目标方法执行前实施增强,比如上面例子的 before()方法
后置通知
org.springframework.aop.AfterReturningAdvice
在目标方法执行后实施增强,比如上面例子的 after()方法
环绕通知
org.aopalliance.intercept.MethodInterceptor
在目标方法执行前后实施增强
异常抛出通知
org.springframework.aop.ThrowsAdvice
在方法抛出异常后实施增强
引介通知
org.springframework.aop.IntroductionInterceptor
在目标类中添加一些新的方法和属性
我们只需要在Spring 的配置文件 applicationContext.xml 进行如下配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1、 创建目标类 -->
<bean id="userService" class="com.my.aop.UserServiceImpl"></bean>
<!--2、创建切面类(通知) -->
<bean id="transaction" class="com.my.aop.one.MyTransaction"></bean>
<!--3、aop编程
3.1 导入命名空间
3.2 使用 <aop:config>进行配置
proxy-target-class="true" 声明时使用cglib代理
如果不声明,Spring 会自动选择cglib代理还是JDK动态代理
<aop:pointcut> 切入点 ,从目标对象获得具体方法
<aop:advisor> 特殊的切面,只有一个通知 和 一个切入点
advice-ref 通知引用
pointcut-ref 切入点引用
3.3 切入点表达式
execution(* com.my.aop.*.*(..))
选择方法 返回值任意 包 类名任意 方法名任意 参数任意
-->
<aop:config>
<!-- 切入点表达式 -->
<aop:pointcut expression="execution(* com.my.aop.*.*(..))" id="myPointCut"/>
<aop:aspect ref="transaction">
<!-- 配置前置通知,注意 method 的值要和 对应切面的类方法名称相同 -->
<aop:before method="before" pointcut-ref="myPointCut"></aop:before>
<aop:after-returning method="after" pointcut-ref="myPointCut"/>
</aop:aspect>
</aop:config>
</beans>
@Test
public void testAop(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService useService = (UserService) context.getBean("userService");
useService.addUser(null);
}
①、 切入点表达式,一个完整的方法表示如下:
execution(modifiers-pattern? ref-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
类修饰符 返回值 方法所在的包 方法名 方法抛出的异常
那么根据上面的对比,我们就很好理解:
- execution(* com.my.aop.*.*(..))
- 选择方法 返回值任意 包 类名任意 方法名任意 参数任意
那么它表达的意思是 返回值任意,包名为 com.ys.aop 下的任意类名中的任意方法名,参数任意。
如果切入点表达式有多个不同目录呢?
<aop:pointcut expression="execution(* com.my.*Service1.*(..)) ||
execution(* com.my.*Service2.*(..))" id="myPointCut"/>
表示匹配 com.my包下的,以 Service1结尾或者以Service2结尾的类的任意方法。
AOP 切入点表达式支持多种形式的定义规则:
1、execution:匹配方法的执行(常用)
execution(public *.*(..))
2.within:匹配包或子包中的方法(了解)
within(com.my.aop