Spring-AOP 面向切面(AspectJ)

SpringAOP 架构 与AspectJ 混用---------------常用

使用AspectJ 实现AOP

所依赖的jar包  除spring基本包之外 还应添加

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.3.9.RELEASE</version>
</dependency>
<!-- AOP联盟的API包 -->
<dependency>
  <groupId>aopalliance</groupId>
  <artifactId>aopalliance</artifactId>
  <version>1.0</version>
</dependency>
<!-- aspectJ织入包 -->
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.9</version>
</dependency>
<!-- spring整合aspectJ -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>4.3.9.RELEASE</version>
</dependency>

工作中基本上是 注解与Xml并存的开发模式

基于AspectJ的注解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/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">

<!-- 开启AspectJ自动代理-->
<aop:aspectj-autoproxy />

</beans>

@AspectJ提供不同的通知类型(定义切面类)

•    @Before 前置通知,相当于BeforeAdvice
•    @AfterReturning 后置通知,相当于AfterReturningAdvice
•    @Around 环绕通知,相当于MethodInterceptor
•    @AfterThrowing异常抛出通知,相当于ThrowAdvice
•    @After 最终final通知,不管是否异常,该通知都会执行
•    @DeclareParents 引介通知,相当于IntroductionInterceptor (类似于 采用拦截器,不要求掌握)

在通知中通过value属性定义切点

•    通过execution函数,可以定义切点的方法切入
•    语法:
–    execution(<访问修饰符>?<返回类型><方法名>(<参数>)<异常>)

匹配所有类public方法

execution(public * *(..))

匹配指定包下所有类方法

execution(* com.imooc.dao.*(..)) 不包含子包
execution(*  com.imooc.dao..*(..))    ..*表示包、子孙包下所有类

匹配指定类所有方法

execution(* com.imooc.service.UserService.*(..))

匹配实现特定接口所有类方法

execution(* com.imooc.dao.GenericDAO+.*(..))

匹配所有save开头的方法

 execution(* save*(..))

@Before前置通知

 可以在方法中传入JoinPoint对象,用来获得切点信息

@Before(value = "execution(* com.yu.demo1.UserDao.add(..))")
public void doBefore(JoinPoint joinPoint) {
    System.out.println("----前置通知----" + joinPoint);
}

@AfterReturing 后置通知

     通过returning属性 可以定义方法返回值,作为参数

@AfterReturning(value = "execution(* com.yu.demo1.UserDao.deleted(..))", returning = "result")
public void doAfterReturing(Object result) {
    System.out.println("----前置通知----" + result);
}

@Around 环绕通知

    around方法的返回值就是目标代理方法执行返回值
    参数为ProceedingJoinPoint 可以调用拦截目标方法执行

重点:如果不调用 ProceedingJoinPoint的 proceed方法,那么目标方法就被拦截了

@Around(value = "execution(* com.yu.demo1.UserDao.update(..))")
public void doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    System.out.println("----环绕通知 前-----");
    Object object = proceedingJoinPoint.proceed(); // 执行目标方法
    System.out.println("----环绕通知 后-----");
}

@AfterThrowing 异常抛出通知

    通过设置throwing属性,可以设置发生异常对象参数

@AfterThrowing(value = "execution(* com.yu.demo1.UserDao.update(..))")
public void doAfterThrowing(Throwable e) throws Throwable {
    System.out.println("----异常跑出通知-----");
}

@After 最终通知

无论是否出现异常,最终通知总是会被执行的

@After(value = "execution(* com.yu.demo1.UserDao.select(..))")
public void doAfter() {
    System.out.println("----最终通知----");
}

通过@Pointcut为切点命名

在每个通知内定义切点,会造成工作量大,不易维护,对于重复的切点,可以使用@Pointcut进行定义
切点方法:private void 无参数方法,方法名为切点名
当通知多个切点时,可以使用 || 进行连接

@AfterReturning(value="myPointcut2()",returning = "result")
public void afterReturing(Object result){
    System.out.println("后置通知=================="+result);
}

@Around(value="myPointcut3()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("环绕前通知================");
    Object obj = joinPoint.proceed(); // 执行目标方法
    System.out.println("环绕后通知================");
    return obj;
}

@Pointcut(value="execution(* com.imooc.aspectJ.demo1.ProductDao.update(..))")
private void myPointcut2(){}

@Pointcut(value="execution(* com.imooc.aspectJ.demo1.ProductDao.delete(..))")
private void myPointcut3(){}

基于AspectJ的XML方式的AOP开发

使用XML配置切面

切面类

public class MyAspectXml {

    // 前置通知
    public void before(JoinPoint joinPoint){
        System.out.println("XML方式的前置通知=============="+joinPoint);
    }

    // 后置通知
    public void afterReturing(Object result){
        System.out.println("XML方式的后置通知=============="+result);
    }

    // 环绕通知
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("XML方式的环绕前通知==============");
        Object obj = joinPoint.proceed();
        System.out.println("XML方式的环绕后通知==============");
        return obj;
    }

    // 异常抛出通知
    public void afterThrowing(Throwable e){
        System.out.println("XML方式的异常抛出通知============="+e.getMessage());
    }

    // 最终通知
    public void after(){
        System.out.println("XML方式的最终通知=================");
    }
}

切面类的配置

    <!--配置切面类-->
    <bean id="myAspectXml" class="com.imooc.aspectJ.demo2.MyAspectXml"/>

配置AOP完成增强

    <!--aop的相关配置=================-->
    <aop:config>
        <!--配置切入点-->
        <aop:pointcut id="pointcut1" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.save(..))"/>
        <aop:pointcut id="pointcut2" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.update(..))"/>
        <aop:pointcut id="pointcut3" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.delete(..))"/>
        <aop:pointcut id="pointcut4" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.findOne(..))"/>
        <aop:pointcut id="pointcut5" expression="execution(* com.imooc.aspectJ.demo2.CustomerDao.findAll(..))"/>
        <!--配置AOP的切面-->
        <aop:aspect ref="myAspectXml">
            <!--配置前置通知-->
            <aop:before method="before" pointcut-ref="pointcut1"/>
            <!--配置后置通知-->
            <aop:after-returning method="afterReturing" pointcut-ref="pointcut2" returning="result"/>
            <!--配置环绕通知-->
            <aop:around method="around" pointcut-ref="pointcut3"/>
            <!--配置异常抛出通知-->
            <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="e"/>
            <!--配置最终通知-->
            <aop:after method="after" pointcut-ref="pointcut5"/>
        </aop:aspect>

    </aop:config>

​ ps: execution表达式-切面排除某个方法

@Pointcut("execution(* com.tellhow.app.controller..*.*(..)) && !execution(* com.tellhow.app.controller..*.action(..))")

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值