spingmvc配置AOP 之 非注解方式

spingmvc配置AOP有两种方式,一种是利用注解的方式配置,另一种是XML配置实现。

应用注解的方式配置:

先在maven中引入AOP用到的依赖

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>4.3.1.RELEASE</version>
    </dependency>
    <!-- aop aspect注解导包-->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.8.6</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.9</version>
    </dependency>

然后在springmvc的配置文件中加入AOP的配置,即扫描AOP的包以及让AOP生效

<!-- AOP 注解方式 ;定义Aspect -->
    <!-- 激活组件扫描功能,在包"com.example.aop及其子包下面自动扫描通过注解配置的组件-->
    <context:component-scan base-package="com.example.aop"/>
    <!-- 启动AspectJ支持   只对扫描过的bean有效-->
    <aop:aspectj-autoproxy proxy-target-class="true" />

如果声明其让其为一个切面。需要我们在xml文件中手动配置。


<!-- 配置切面的Bean -->
    <bean id="sysAspect" class="com.example.aop.SysAspect"/>
    <!-- 配置AOP -->
    <aop:config>
        <!-- 配置切点表达式  -->
        <aop:pointcut id="pointcut" expression="execution(public * com.example.controller.*Controller.*(..))"/>
        <!-- 配置切面及配置 -->
        <aop:aspect order="3" ref="sysAspect">
            <!-- 前置通知 -->
            <aop:before method="beforMethod"  pointcut-ref="pointcut" />
            <!-- 后置通知 -->
            <aop:after method="afterMethod"  pointcut-ref="pointcut"/>
            <!-- 返回通知 -->
            <aop:after-returning method="afterReturnMethod" pointcut-ref="pointcut" returning="result"/>
            <!-- 异常通知 -->
            <aop:after-throwing method="afterThrowingMethod" pointcut-ref="pointcut" throwing="ex"/>
            <aop:around method="aroundMethod" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>

可以看到,这个类除了没有@Aspect以及相关切面的注解外,跟正常的AOP切面类没有差别。

定义的切面bean就是我们自定义的切面类,然后配置AOP(<aop:config>)。先定义切面范围pointcut。余下的就是制定aop的切面类、优先级然后再详细配置切面的通知。这样就跟注解的方式产生的效果一致了。

package com.example.aop;

import java.util.Arrays;
import java.util.List;

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

@Component //该标签把LoggerAspect类放到IOC容器中
public class SysAspect {

    /**
     * 前置通知
     * @param joinPoint
     */
    public void beforMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        List<Object> args = Arrays.asList(joinPoint.getArgs());
        System.out.println("this method "+methodName+" begin. param<"+ args+">");
    }
    /**
     * 后置通知(无论方法是否发生异常都会执行,所以访问不到方法的返回值)
     * @param joinPoint
     */
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("this method "+methodName+" end.");
    }
    /**
     * 返回通知(在方法正常结束执行的代码)
     * 返回通知可以访问到方法的返回值!
     * @param joinPoint
     */
    public void afterReturnMethod(JoinPoint joinPoint,Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("this method "+methodName+" end.result<"+result+">");
    }
    /**
     * 异常通知(方法发生异常执行的代码)
     * 可以访问到异常对象;且可以指定在出现特定异常时执行的代码
     * @param joinPoint
     * @param ex
     */
    public void afterThrowingMethod(JoinPoint joinPoint,Exception ex){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("this method "+methodName+" end.ex message<"+ex+">");
    }
    /**
     * 环绕通知(需要携带类型为ProceedingJoinPoint类型的参数)
     * 环绕通知包含前置、后置、返回、异常通知;ProceedingJoinPoin 类型的参数可以决定是否执行目标方法
     * 且环绕通知必须有返回值,返回值即目标方法的返回值
     * @param point
     */
    public Object aroundMethod(ProceedingJoinPoint point){

        Object result = null;
        String methodName = point.getSignature().getName();
        try {
            //前置通知
            System.out.println("The method "+ methodName+" start. param<"+ Arrays.asList(point.getArgs())+">");
            //执行目标方法
            result = point.proceed();
            //返回通知
            System.out.println("The method "+ methodName+" end. result<"+ result+">");
        } catch (Throwable e) {
            //异常通知
            System.out.println("this method "+methodName+" end.ex message<"+e+">");
            throw new RuntimeException(e);
        }
        //后置通知
        System.out.println("The method "+ methodName+" end.");
        return result;
    }
}
posted @ 2021-10-08 09:51  不良徐某  阅读(140)  评论(0编辑  收藏  举报