Spring框架内容整理(三):AOP

AOP面向切面

切面支持类

切面就是通知和切入点的组合,而切面是通过配置方式定义的,因此这定义切面前,我们需要定义切面支持类,切面支持类提供了通知实现

package cn.javass.spring.chapter6.aop;
public class HelloWorldAspect {
    //前置通知
    public void beforeAdvice() {
        System.out.println("===========before advice");
    }
    //后置最终通知
    public void afterFinallyAdvice() {
        System.out.println("===========after finally advice");
    }
}

HelloWorldAspect类不是真正的切面实现,只是定义了通知实现的类,在此我们可以把它看作就是缺少了切入点的切面。

Schema XML配置AOP

1)首先配置AOP需要aop命名空间

<?xml version="1.0" encoding="UTF-8"?>
<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/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
</ beans>

2)配置目标类:

< bean id="helloWorldService" class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/>

3)配置切面:

<!--切面支持类-->
<bean id="aspect" class="cn.javass.spring.chapter6.aop.HelloWorldAspect"/> //
<aop:config>
    <!-- 切点 -->
    <aop:pointcut id="pointcut" expression="execution(* cn.javass..*.*(..))"/>
    <!-- 切面 -->
    <aop:aspect ref="aspect">
        <!-- 前置通知 -->
        <aop:before pointcut-ref="pointcut" method="beforeAdvice"/>
        <!-- 后置最终通知 -->
        <aop:after pointcut="execution(* cn.javass..*.*(..))" method="afterFinallyAdvice"/>
    </aop:aspect>
</aop:config>

配置解析:
< aop:pointcut>:用来定义切入点,该切入点可以重用; expression属性:定义切入点模式,默认是AspectJ语法,
< aop:aspect>:切面,其中“ref”用来引用切面支持类的方法
< aop:before>:前置通知,pointcut-ref属性用于引用切入点Bean,而method用来引用切面
通知实现类中的方法,该方法就是通知实现,即在目标类方法执行之前调用的方法。
< aop:after >:后置通知,除了使用pointcut-ref属性来引用已经存在的切入点,也可以使用pointcut属性来定义,如pointcut=”execution(* cn.javass...(..))”,method属性同样是指定通知实现,即在目标类方法执行之后调用的方法。

这里写图片描述

Spring AOP框架生成AOP代理过程

Spring AOP框架生成AOP代理过程


AOP配置解析

切面

切面就是包含切入点和通知的对象,在Spring容器中将被定义为一个Bean该支持Bean的字段和方法提供了切面的状态和行为信息,并通过配置方式来指定切入点和通知实现。

切面使用< aop:aspect>标签指定,ref属性用来引用切面支持Bean。

切点

在< aop:config>标签下使用< aop:pointcut>声明一个切入点Bean,该切入点可以被多个切面使用,expression属性指定切入点表达式

匿名切入点Bean,可以在声明通知时通过pointcut属性指定切入点表达式,该切入点是匿名切入点,只被该通知使用

<aop:config>
    <aop:aspect ref="aspectSupportBean">
        <aop:after pointcut="execution(* cn.javass..*.*(..))" method="afterFinallyAdvice"/>
    </aop:aspect>
</aop:config>
声明通知

前置通知:在切入点选择的方法之前执行,通过< aop:aspect>标签下的< aop:before>标签声明:

<bean id="helloWorldService"
    class="cn.javass.spring.chapter6.service.impl.HelloWorldService"/>
<bean id="aspect" class="cn.javass.spring.chapter6.aop.HelloWorldAspect"/>
<aop:config>
    <aop:aspect ref="aspect">
    <aop:before pointcut="execution(* cn.javass..*.sayBefore(..)) and args(param)"
        method="beforeAdvice(java.lang.String)" arg-names="param"/>
    </aop:aspect>
</aop:config>

使用“args(param)”匹配目标方法只有一个参数且传入的参数类型为通知实现方法中同名的参数类型
使用method=” beforeAdvice(java.lang.String) “指定前置通知实现方法,且该通知有一个参数类型为java.lang.String参数;

后置返回通知
在切入点选择的方法正常返回时执行,通过< aop:aspect>标签下的< aop:after-returning>标签声明:

<aop:after-returning pointcut="切入点表达式" pointcut-ref="切入点Bean引用"
    method="后置返回通知实现方法名"
    arg-names="后置返回通知实现方法参数列表参数名字"
    returning="返回值对应的后置返回通知实现方法参数名"
/>

returning:定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法执行正常返回后,将把目标方法返回值传给通知方 法;returning限定了只有目标方法返回值匹配与通知方法相应参数类型时才能执行后置返回通知,否则不执行,对于returning对应的通知方法 参数为Object类型将匹配任何目标返回值

AspectJ方式配置AOP

Spring除了支持Schema方式配置AOP,还支持注解方式:使用@AspectJ风格的切面声明
Spring默认不支持@AspectJ风格的切面声明,开启配置
< aop:aspectj-autoproxy/>

切面

使用@Aspect注解进行声明

@Aspect()
Public class Aspect{
    .....
}
<bean id="aspect" class="……Aspect"/>
切点

@Pointcut+方法(方法必须是返回void类型)实现

@Pointcut(value=”切入点表达式”, argNames = “参数名列表”)
public void pointcutName(……) {}

  • value:指定切入点表达式;
  • argNames:指定命名切入点方法参数列表参数名字,可以有多个用“,”分隔,这些参数将传递给通知方法同名的参数,同时比如切入点表达式“args(param)”将匹配参数类型为命名切入点方法同名参数指定的参数类型。
  • pointcutName:切入点名字,可以使用该名字进行引用该切入点表达式。
@Pointcut(value="execution(* cn.javass..*.sayAdvisorBefore(..)) && args(param)", argNames = "param")
public void beforePointcut(String param) {}
声明通知

一、前置通知

@Before(value = "切入点表达式或命名切入点", argNames = "参数列表参数名")
@Before(value = "beforePointcut(param)", argNames = "param")
public void beforeAdvice(String param) {
    System.out.println("===========before advice param:" + param);
}

二、后置返回通知

/*
    value:指定切入点表达式或命名切入点;
    pointcut:同样是指定切入点表达式或命名切入点,如果指定了将覆盖value属性指定的,pointcut具有高优先级;
    argNames:与Schema方式配置中的同义;
    returning:与Schema方式配置中的同义。
*/
@AfterReturning(
    value="切入点表达式或命名切入点",
    pointcut="切入点表达式或命名切入点",
    argNames="参数列表参数名",
    returning="返回值对应参数名")       

切面、切入点、通知全部使用注解完成:
1)使用@Aspect将POJO声明为切面;
2)使用@Pointcut进行命名切入点声明,
3)使用@Before进行前置通知声明,其中value用于定义切入点表达式或引用命名切入点;
4)配置文件需要使用< aop:aspectj-autoproxy/>来开启注解风格的@AspectJ支持;
5)需要将切面注册为Bean,如“aspect”Bean;

expression类型匹配语法
* :匹配任何数量字符;
.. :(两个点)匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数。
+ : 匹配指定类型的子类型;仅能作为后缀放在类型模式后边

这里写图片描述

Spring代理机制

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值