spring(三)-三种AOP实现方式

一、配置文件与接口方式

1、前置通知

1.1、实现 MethodBeforeAdvice 接口并重写 before(Method method, Object[] args, Object target) 方法

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

/**
 * 前置通知
 */
public class AddUserBefore implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("*********************前置通知*********************");
        System.out.println("方法名:"+method.getName());
        System.out.println("参数个数:"+method.getParameterCount());
        System.out.println("参数个数:"+args.length);
        System.out.println("对象:"+target.toString());
    }
}

1.2、编写配置文件

	<bean id="addUserBefore" class="aop.AddUserBefore"></bean>
	<!-- 前置通知   -->
    <aop:config>
        <!--   切入点     -->
        <aop:pointcut id="pointcutBrfore"  expression="execution(public boolean service.IAddUserService.addUser(entity.User))"/>
        <!--   切面与切入点连接关系     -->
        <aop:advisor  advice-ref="addUserBefore" pointcut-ref="pointcutBrfore"/>
    </aop:config>
2、后置通知

2.1、实现 AfterReturningAdvice 接口并重写 afterReturning(Object returnValue, Method method, Object[] args, Object target) 方法

import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;

/**
 * 后置通知
 */
public class AddUserAfterReturning implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("*********************后置通知*********************");
        System.out.println("返回值:"+returnValue);
        System.out.println("方法名:"+method.getName());
        System.out.println("参数个数:"+method.getParameterCount());
        System.out.println("参数个数:"+args.length);
        System.out.println("对象:"+target.toString());
    }
}

2.2、编写配置文件

	<bean id="AddUserAfterReturning" class="aop.AddUserAfterReturning">				</bean>
	<!--  后置通知  -->
    <aop:config>
        <aop:pointcut id="pointcutAfterReturning" expression="execution(public boolean service.IAddUserService.addUser(entity.User))"/>
        <aop:advisor  advice-ref="AddUserAfterReturning" pointcut-ref="pointcutAfterReturning"></aop:advisor>
    </aop:config>
3、异常通知

3.1、实现 ThrowsAdvice 接口并重写 afterThrowing(Exception ex)afterThrowing(Method method, Object[] args, Object target, Exception ex)方法中的一种


import org.springframework.aop.ThrowsAdvice;
import java.lang.reflect.Method;

/**
 * 异常通知
 */
public class AddUserThrowing implements ThrowsAdvice {

    /**
     * 两种方只需重写其中一种
     * @param ex
     */
    public void afterThrowing(Exception ex){
        System.out.println("*********************异常通知1*********************");
        System.out.println("异常信息:"+ex.getMessage());
    }

    /**
     * 两种方只需重写其中一种
     * @param ex
     */
    public void afterThrowing(Method method, Object[] args, Object target, Exception ex){
        System.out.println("*********************异常通知2*********************");
        System.out.println("方法名:"+method.getName());
        System.out.println("参数个数:"+method.getParameterCount());
        System.out.println("参数个数:"+args.length);
        System.out.println("对象:"+target.toString());
        System.out.println("异常信息:"+ex.getMessage());
    }
}

3.2、编写配置文件

	<bean id="addUserThrowing" class="aop.AddUserThrowing"></bean>
	<!-- 异常通知   -->
    <aop:config>
        <aop:pointcut id="pointCutThrowing" expression="execution(public boolean service.IAddUserService.addUser(entity.User))"/>
        <aop:advisor  advice-ref="addUserThrowing" pointcut-ref="pointCutThrowing"></aop:advisor>
    </aop:config>
4、环绕通知

4.1、实现 MethodInterceptor 接口并重写 invoke(MethodInvocation invocation) 方法


import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

/**
 * 环绕通知
 */
public class AddUserAround implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("*********************环绕通知*********************");
        Object proceed = null;
        try {
            System.out.println("*********************环绕通知>>>>前置通知*********************");
            //执行方法
            proceed = invocation.proceed();
            System.out.println("*********************环绕通知>>>>后置通知*********************");
            System.out.println("\n**********************************************************************************");
            //执行方法的返回值
            System.out.println("返回值:" +proceed);
            System.out.println("方法名:" + invocation.getMethod().getName());
            System.out.println("参数个数:" + invocation.getArguments().length);
            System.out.println("对象:" + invocation.getThis());
        }catch (Exception e){
            System.out.println("*********************环绕通知>>>>异常通知*********************");
        }
        //可修改 proceed ,改变最终的返回结果
        return proceed ;
    }
}

4.2、编写配置文件

	<bean id="addUserAround" class="aop.AddUserAround"></bean>
	<!--  环绕通知  -->
    <aop:config>
        <aop:pointcut id="pointCutAroud" expression="execution(public boolean service.IAddUserService.addUser(..))"/>
        <aop:advisor  advice-ref="addUserAround" pointcut-ref="pointCutAroud"></aop:advisor>
    </aop:config>

二、Schema方式

1、创建通知类
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class AdviceSchema {
    /**
     * 前置通知
     * @param joinPoint
     */
    public void before(JoinPoint joinPoint){
        System.out.println("********************注解----->前置通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
    }

    /**
     * 后置通知
     * @param joinPoint
     * @param returnVal
     */
    public void afterReturning(JoinPoint joinPoint,Object returnVal){
        System.out.println("********************注解----->后置通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
        System.out.println("返回值:"+returnVal);
    }

    /**
     * 异常通知
     */
    public void throwing(JoinPoint joinPoint,Exception ex){
        System.out.println("********************注解----->异常通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
        System.out.println("异常信息:"+ex.getMessage());
    }

    /**
     * 环绕通知
     * @param joinPoint
     * @return
     */
    public Object around(ProceedingJoinPoint joinPoint){
        System.out.println("********************注解----->环绕通知******************");
        try {
            System.out.println("********************注解----->环绕通知----->前置通知******************");
            Object proceed = joinPoint.proceed();
            System.out.println("返回值:"+proceed);
            System.out.println("方法名:"+joinPoint.getSignature().getName());
            System.out.println("参数个数:"+joinPoint.getArgs().length);
            System.out.println("对象:"+joinPoint.getThis());
            System.out.println("对象:"+joinPoint.getTarget());
            System.out.println("********************注解----->环绕通知----->后置通知******************");
        }catch (Throwable e){
            System.out.println("********************注解----->环绕通知----->异常通知******************");
        }finally {
            System.out.println("********************注解----->环绕通知----->最终通知******************");
        }
        return true;
    }
    
    /**
     * 最终通知
     * @param joinPoint
     */
    public void after(JoinPoint joinPoint){
        System.out.println("********************注解----->最终通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
    }
}
2、配置Schema
		<bean id="adviceSchema" class="aop.AdviceSchema"></bean>
		<aop:config>
            <aop:pointcut id="pointcut" expression="execution(public boolean service.IAddUserService.addUser(..))"/>
            <aop:aspect ref="adviceSchema">
                <!--      前置通知          -->
                <aop:before method="before" pointcut-ref="pointcut"></aop:before>
                <!--      后置通知          -->
                <aop:after-returning method="afterReturning" returning="returnVal" pointcut-ref="pointcut"></aop:after-returning>
                <!--      异常通知          -->
                <aop:after-throwing method="throwing" throwing="ex" pointcut-ref="pointcut"></aop:after-throwing>
                <!--      最终通知          -->
                <aop:after method="after" pointcut-ref="pointcut"></aop:after>
                <!--      环绕通知          -->
                <aop:around method="around" pointcut-ref="pointcut"></aop:around>
            </aop:aspect>
        </aop:config>

三、注解方式

1、配置扫描器与开启 AOP 支持
<!--  扫描器:扫描 指定包中包含@Component、@Service、@Repository、@Controller 的类并将该类加入 IOC 容器中      -->
        <context:component-scan base-package="entity,dao.impl,service,aop"/>
        <!--  开启aop自动代理  -->
        <aop:aspectj-autoproxy/>
2、创建通知类

2.1、@Before(value = "advice()") 中的方法需要带括号
2.2、@AfterReturning(pointcut = "advice()",returning ="returnVal" ) 中的 returning ="returnVal" 为后置通知的返回值参数名,修改 returnVal 无法改变最终的返回值
2.3、@AfterThrowing(pointcut = "advice()",throwing = "ex") 中的 throwing = "ex" 为 异常通知中的异常参数名
2.4、public Object around(ProceedingJoinPoint joinPoint) 环绕通知的参数类型不同于其他通知,参数类型为 ProceedingJoinPoint;修改环绕通知中的Object proceed = joinPoint.proceed();proceed 的值,可改变最终的返回结果

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

/**
 * 注解形式的 AOP
 */
@Component
@Aspect
public class AdviceAnnotation {
	
	//定义一个切入点
    @Pointcut(value = "execution(public boolean service..*.*(..))")
    public void advice(){}

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before(value = "advice()")
    public void before(JoinPoint joinPoint){
        System.out.println("********************注解----->前置通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
    }

    /**
     * 后置通知
     * @param joinPoint
     * @param returnVal
     */
    @AfterReturning(pointcut = "advice()",returning ="returnVal" )
    public void afterReturning(JoinPoint joinPoint,Object returnVal){
        System.out.println("********************注解----->后置通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
        System.out.println("返回值:"+returnVal);
    }

    /**
     * 异常通知
     */
    @AfterThrowing(pointcut = "advice()",throwing = "ex")
    public void throwing(JoinPoint joinPoint,Exception ex){
        System.out.println("********************注解----->异常通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
        System.out.println("异常信息:"+ex.getMessage());
    }

    /**
     * 最终通知
     * @param joinPoint
     */
    @After(value = "advice()")
    public void after(JoinPoint joinPoint){
        System.out.println("********************注解----->最终通知******************");
        System.out.println("方法名:"+joinPoint.getSignature().getName());
        System.out.println("参数个数:"+joinPoint.getArgs().length);
        System.out.println("对象:"+joinPoint.getThis());
        System.out.println("对象:"+joinPoint.getTarget());
    }

    /**
     * 环绕通知
     * @param joinPoint
     * @return
     */
    @Around(value = "advice()")
    public Object around(ProceedingJoinPoint joinPoint){
        System.out.println("********************注解----->环绕通知******************");
        try {
            System.out.println("********************注解----->环绕通知----->前置通知******************");
            Object proceed = joinPoint.proceed();
            System.out.println("返回值:"+proceed);
            System.out.println("方法名:"+joinPoint.getSignature().getName());
            System.out.println("参数个数:"+joinPoint.getArgs().length);
            System.out.println("对象:"+joinPoint.getThis());
            System.out.println("对象:"+joinPoint.getTarget());
            System.out.println("********************注解----->环绕通知----->后置通知******************");
        }catch (Throwable e){
            System.out.println("********************注解----->环绕通知----->异常通知******************");
        }finally {
            System.out.println("********************注解----->环绕通知----->最终通知******************");
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值