【Java】SpringAOP五种增强

增强类型

增强又称通知(Advice),指代植入切面的事件,增强(通知)有以下几种类型:

  1. 前置(before):在方法执行之前执行通知
  2. 后置(after):在方法执行后通知,无论其结果如何
  3. 后置返回(after-returning):只有方法成功完成后才能在方法执行和执行通知
  4. 后置异常(after-throwing):只有方法抛出异常而退出方法执行后才能运行通知
  5. 环绕(around):在调用通知方法之前和之后运行通知
通过实现接口的方式实现增强

首先要明确我们实现上述五种通知需要实现哪些接口。

通知类型接口
Beforeorg.springframework.aop.MethodBeforeAdvice
AfterReturnorg.springframework.aop.AfterReturningAdvice
AfterThroworg.springframework.aop.ThrowsAdvice
Aroundorg.aopalliance.intercept.MethodInterceptor
//前置增强:BeforeAdvisor.java
package com.aop.advisor;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;


public class BeforeAdvisor implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("--- 前置通知 --");
    }

}

//后置返回增强:AfterReturnAdvisor.java
package com.aop.advisor;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterReturnAdvisor implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("--- 后置返回通知 ----");
    }

}

//异常增强:ThrowsAdvisor.java
package com.aop.advisor;

import org.springframework.aop.ThrowsAdvice;

public class ThrowsAdvisor implements ThrowsAdvice {

    public void afterThrowing(Exception e) throws Throwable{
        System.out.println("-- 异常通知 --");
    }

}

配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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">

    <bean id="service" class="com.aop.service.Service"></bean>

    <bean id="beforeAdvisor" class="com.aop.advisor.BeforeAdvisor"></bean>

    <bean id="afterReturnAdvisor" class="com.aop.advisor.AfterReturnAdvisor"></bean>

    <bean id="throwsAdvisor" class="com.aop.advisor.ThrowsAdvisor"></bean>


    <aop:config>

        <aop:pointcut id="test" expression="execution(* com.aop.service.*.*(..))" />

        <aop:advisor advice-ref="beforeAdvisor" id="beforeAdvice" pointcut-ref="test"/>

        <aop:advisor advice-ref="afterReturnAdvisor" id="afterReturnAdvice" pointcut-ref="test"/>

        <aop:advisor advice-ref="throwsAdvisor" id="throwsAdvice" pointcut-ref="test"/>

    </aop:config>

</beans>

测试用例如下:

//Service.java
package com.aop.service;

public class Service {

    public void print(){
        System.out.println("service方法被调用");
    }

    public void error(){
        int a =1/0;
    }

}

//TestMain.java
package com.aop;

import com.aop.service.Service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestMain {

    public static void main(String[] args) {

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring-mvc.xml");
        Service service = (Service) ac.getBean("service");
        service.print();
        service.error();

    }
    
}

测试结果如下:
在这里插入图片描述

通过AspectJ实现增强

我们需要创建描述增强的类。

//AspectJAdvisor.java
package com.aop.advisor;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class AspectJAdvisor {

    public void before(JoinPoint joinPoint){
        String res = "[+]前置通知 targetObject:" + joinPoint.getTarget()
                    +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    public void after(JoinPoint joinPoint){
        String res = "[+]后置通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    public void afterReturn(JoinPoint joinPoint){
        String res = "[+]后置返回通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    public void afterThrow(JoinPoint joinPoint){
        String res = "[+]后置抛错通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    /**
     * ProceedingJoinPoint只支持Around Advice
     * @param joinPoint
     */
    public void around(ProceedingJoinPoint joinPoint){
        String res = "[+]环绕前置通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        String ret = "[+]环绕后置通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(ret);

    }

}

配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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">

    <bean id="service" class="com.aop.service.Service"></bean>

    <bean id="aspectJAdvisor" class="com.aop.advisor.AspectJAdvisor"></bean>

    <aop:config>

        <aop:aspect ref="aspectJAdvisor">

            <aop:pointcut id="test" expression="execution(* com.aop.service.*.*(..))"/>

            <aop:before method="before" pointcut-ref="test"/>

            <aop:after method="after" pointcut-ref="test"/>

            <aop:after-returning method="afterReturn" pointcut-ref="test"/>

            <aop:after-throwing method="afterThrow" pointcut-ref="test"/>

            <aop:around method="around" pointcut-ref="test"/>

        </aop:aspect>

    </aop:config>

</beans>

测试用例继续使用通过接口实现增强中的用例。我们得出的结果如下:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

使用AspectJ+注解的方式实现增强
package com.aop.advisor;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class AspectJAdvisor {

    @Pointcut("execution(* com.aop.service.Service.print())")
    private void pointCutOnPrint(){}

    @Pointcut("execution(* com.aop.service.Service.error())")
    private void pointCutOnError(){}

    @Before("pointCutOnPrint()")
    public void before(JoinPoint joinPoint){
        String res = "[+]前置通知 targetObject:" + joinPoint.getTarget()
                    +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    @After("pointCutOnPrint()")
    public void after(JoinPoint joinPoint){
        String res = "[+]后置通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    @AfterReturning("pointCutOnPrint()")
    public void afterReturn(JoinPoint joinPoint){
        String res = "[+]后置返回通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    @AfterThrowing("pointCutOnError()")
    public void afterThrow(JoinPoint joinPoint){
        String res = "[+]后置抛错通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
    }

    /**
     * ProceedingJoinPoint只支持Around Advice
     * @param joinPoint
     */
    @Around("pointCutOnPrint()")
    public void around(ProceedingJoinPoint joinPoint){
        String res = "[+]环绕前置通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(res);
        try {
            joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        String ret = "[+]环绕后置通知 targetObject:" + joinPoint.getTarget()
                +" kind:" + joinPoint.getKind();
        System.out.println(ret);

    }

}

配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       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
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="com"></context:component-scan>

    <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"></aop:aspectj-autoproxy>


    <bean id="service" class="com.aop.service.Service"></bean>

</beans>

测试用例不变,结果如图
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值