spring 面向切面 解析

一、xml配置方式

    <!-- 目标对象
    arithmeticCalculatorImpl类,是实现 add sub mul dvi (加减乘除)四个方法的类。这个类就是目标对象,即在计算的前后加上日志。
    -->
    <bean id="arithmeticCalculatorImpl" class="com.atguigu.spring.aspectJ.xml.ArithmeticCalculatorImpl"></bean>
    
    <!--切面类
     LoggingAspect记录日志的类,有5个方法
     beforeMethod: 被注入方法(比如add方法)执行前执行的方法;
     afterMethod: 被注入方法(比如add方法)执行后执行的方法;
     afterReturningMethod: 被注入方法(比如add方法)执行返回时执行的,
     如果add方法异常,则此方法不执行;
     afterThrowingMethod: 被注入方法(比如add方法)出现异常后执行的方法;
     aroundMethod: 可以实现上述四种方法。
    -->
    <bean id="loggingAspect" class="com.atguigu.spring.aspectJ.xml.LoggingAspect">
    </bean>
    
    <bean id="validationAspect" class="com.atguigu.spring.aspectJ.xml.ValidationAspect">
    </bean>
    
    <!-- AOP: 切面  通知  切入点表达式 -->
    <aop:config>
        <!-- 切面 -->
        <aop:aspect ref="loggingAspect" order="2">
        
            <!-- 切入点表达式 -->
            <aop:pointcut expression="execution(* com.atguigu.spring.aspectJ.xml.*.*(..))" id="myPointCut"/>
        
            <!-- 通知 -->
            <aop:before method="beforeMethod"  pointcut-ref="myPointCut"/>
            <aop:after method="afterMethod"  pointcut-ref="myPointCut"/>
            <aop:after-returning method="afterReturningMethod" pointcut-ref="myPointCut" returning="result"/>
            <aop:after-throwing method="afterThrowingMethod" pointcut-ref="myPointCut" throwing="ex"/>
            <!-- <aop:around method="aroundMethod" pointcut-ref="myPointCut"/> -->    
        
        </aop:aspect>    
        <aop:aspect ref="validationAspect" order="1">
            <aop:before method="beforeMethod" pointcut-ref="myPointCut"/>
        </aop:aspect>        
    </aop:config>    
</beans>

/**
 * 日志切面
 */

public class LoggingAspect {

    public void  beforeMethod(JoinPoint joinPoint) {
        //获取方法的参数
        Object [] args = joinPoint.getArgs();
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        
        System.out.println("LoggingAspect==> The method "+methodName+" begin with "+ Arrays.asList(args));
    }
    
    public void afterMethod(JoinPoint joinPoint) {
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        System.out.println("LoggingAspect==> The method " + methodName +" ends .");
    }
    
    public void afterReturningMethod(JoinPoint joinPoint,Object result ) {
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        System.out.println("LoggingAspect==> The method " + methodName + " end with :" + result );
    }
    
    
    public void afterThrowingMethod(JoinPoint joinPoint,ArithmeticException ex ) {
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        
        System.out.println("LoggingAspect==> Thew method " + methodName + " occurs Exception: " +ex );
    }
    
    public  Object  aroundMethod(ProceedingJoinPoint pjp) {
        
        //执行目标方法
        try {
            //前置
            Object result = pjp.proceed();
            //返回
            return result ; 
        } catch (Throwable e) {
            //异常通知
            e.printStackTrace();
        }finally {
            // 后置
        }
        
        return null;
    }
    
}


二、注解方式
<?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:context="http://www.springframework.org/schema/context"
    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/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
    
    <!-- 组件扫描 -->
    <context:component-scan base-package="com.atguigu.spring.aspectJ.annotation"></context:component-scan>

    <!-- 基于注解使用AspectJ: 主要的作用是为切面中通知能作用到的目标类生成代理.  -->
    <aop:aspectj-autoproxy/>
</beans>


package com.atguigu.spring.aspectJ.annotation;

import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 日志切面
 */

@Component  //标识为一个组件
@Aspect     //标识为一个切面
@Order(2)   // 切面类执行的优先级,即执行顺序,order后数字越小,优先级越高
public class LoggingAspect {

    /**
     * 声明切入点表达式
     */
    @Pointcut("execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))")
    public void declarePointCut() {}

    /**
     * 前置通知: 在目标方法(连接点)执行之前执行. 
     */
    @Before("execution(public int com.atguigu.spring.aspectJ.annotation.ArithmeticCalculatorImpl.add(int,int))")
    public void  beforeMethod(JoinPoint joinPoint) {
        //获取方法的参数
        Object [] args = joinPoint.getArgs();
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        
        System.out.println("LoggingAspect==> The method "+methodName+" begin with "+ Arrays.asList(args));
    }
    
    /**
     * 后置通知: 在目标方法执行之后执行, 不管目标方法有没有抛出异常.  不能获取方法的结果
     *    * com.atguigu.spring.aspectJ.annotation.*.*(..)
     *    * : 任意修饰符 任意返回值
     *    * : 任意类
     *    * : 任意方法
     *    ..: 任意参数列表
     *    
     * 连接点对象: JoinPoint
     */
    
    //@After("execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))")
    @After("declarePointCut()")
    public void afterMethod(JoinPoint joinPoint) {
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        System.out.println("LoggingAspect==> The method " + methodName +" ends .");
        
    }
    
    /**
     * 返回通知: 在目标方法正常执行结束后执行.  可以获取到方法的返回值. 
     * 
     * 获取方法的返回值: 通过returning 来指定一个名字, 必须要与方法的一个形参名一致. 
     */
    
    //@AfterReturning(value="execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))",returning="result")
    @AfterReturning(value="declarePointCut()",returning="result")
    public void afterReturningMethod(JoinPoint joinPoint, Object result ) {
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        System.out.println("LoggingAspect==> The method " + methodName + " end with :" + result );
    }
    
    /**
     * 异常通知: 在目标方法抛出异常后执行. 
     * 
     * 获取方法的异常: 通过throwing来指定一个名字, 必须要与方法的一个形参名一致. 
     * 
     * 可以通过形参中异常的类型 来设置抛出指定异常才会执行异常通知. 
     * 
     */
    @AfterThrowing(value="execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))",throwing="ex")
    public void afterThrowingMethod(JoinPoint joinPoint,ArithmeticException ex ) {
        //方法的名字
        String methodName = joinPoint.getSignature().getName();
        
        System.out.println("LoggingAspect==> Thew method " + methodName + " occurs Exception: " +ex );
    }
    
    /**
     * 环绕通知: 环绕着目标方法执行. 可以理解是 前置 后置 返回  异常 通知的结合体,更像是动态代理的整个过程. 
     */
    
    @Around("execution(* com.atguigu.spring.aspectJ.annotation.*.*(..))")
    public  Object  aroundMethod(ProceedingJoinPoint pjp) {
        
        //执行目标方法
        try {
            //前置
            Object result = pjp.proceed();
            //返回
            return result ; 
        } catch (Throwable e) {
            //异常通知
            e.printStackTrace();
        }finally {
            // 后置
        }
        
        return null;
    }
    
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值