首页 > 其他分享 >Spring基础使用六

Spring基础使用六

时间:2022-10-29 14:55:36浏览次数:47  
标签:int Spring org 基础 annotation result 使用 import public

Spring基础使用六

基于注解的AOP

使用AspectJ注解层

具体实现层:

  • 动态代理:有接口情况
  • cglib:没接口情况
  • 动态代理:JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口
  • cglib:通过继承被代理的目标类实现代理,所以不需要目标类实现接口。
  • AspectJ:本质上是静态代理,将代理逻辑“织入”被代理的目标类编译得到的字节码文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解。

Aspect

    1. 在切面中,需要通过指定的注解将方法标识为通知方法
  • @Before:前置通知,在目标对象方法执行之前执行
  • @After:后置通知,在目标对象的方法执行之后执行
  • @AfterReturning:返回通知,在目标对象方法返回值返回之后执行
  • @AfterThrowing:异常通知,在目标对象方法的catch字句中执行
  • @Around:环绕通知
    1. 切入点表达式:
  • @Before("execution(public int com.wfy.aop.annotation.CalculatorImpl.add(int, int))")
  • 简写表达式:
  • @Before("execution(* com.wfy.aop.annotation.CalculatorImpl.*(..))")
  • 第一个*表示任意的访问修饰符和返回值类型
  • 第二个*表示类中任意的方法
  • ..表示任意的参数列表
  • 类的地方也可以使用*,表示包下所有的类
    1. 重用切入点表达式
  • //@Pointcut就是用来声明一个公共的切入点表达式
  • @Pointcut("execution(* com.wfy.aop.annotation.CalculatorImpl.*(..))")
  • public void pointCut(){}
    
  • 使用方式: @Before("pointCut()")
    1. 获取连接点信息
  • 在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
  • //获取连接点所对应方法的签名信息
  • Signature signature = joinPoint.getSignature();
  • //获取连接点所对应方法的参数
  • Object[] args = joinPoint.getArgs();
  • 5.切面的优先级
  • 可以通过@Order注解的value属性设置优先级,默认值Integer的最大值
  • @Order注解的value属性值越小,优先级越高

导入项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wfy</groupId>
    <artifactId>spring-05-aop</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
<dependencies>
    <!--基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.23</version>
    </dependency>
    <!--junit测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
<!--    spring-aspects会帮我们传递过来aspectjweaver-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

</project>

映射文件

<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">

<!--
     AOP的注意事项:
     切面类和目标类都需要交给IOC容器进行管理
     切面类必须通过@Aspect注解标识为一个切面
     在Spring的配置文件中设置<aop:aspectj-autoproxy/>开启基于注解的aop

-->
<context:component-scan base-package="com.wfy.aop.annotation"></context:component-scan>

<!--开启基于注解的aop功能-->
    <aop:aspectj-autoproxy/>
</beans>

接口

package com.wfy.aop.annotation;

public interface Calculator {

    int add(int i , int j);

    int sub(int i,int j);

    int mul(int i , int j);

    int div(int i , int j);
}

实现类

package com.wfy.aop.annotation;


import org.springframework.stereotype.Component;

@Component
public class CalculatorImpl implements Calculator {
    @Override
    public int add(int i, int j) {
        int result = i + j;
        System.out.println("方法内部 , result: "+result);
        return result;
    }

    @Override
    public int sub(int i, int j) {
        int result = i - j;
        System.out.println("方法内部 , result: "+result);
        return result;
    }

    @Override
    public int mul(int i, int j) {
        int result = i * j;
        System.out.println("方法内部 , result: "+result);
        return result;
    }

    @Override
    public int div(int i, int j) {
        int result = i / j;
        System.out.println("方法内部 , result: "+result);
        return result;
    }
}

LoggerAspect代理切面

package com.wfy.aop.annotation;

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

import java.util.Arrays;

@Component
@Aspect //将当前组件标识为切面
public class LoggerAspect {

    @Pointcut("execution(* com.wfy.aop.annotation.CalculatorImpl.*(..))")
    public void pointCut(){}

    @Before("pointCut()")
 // @Before("execution(public int com.wfy.aop.annotation.CalculatorImpl.add(int, int))")
    public void beforeAdviceMethod(JoinPoint joinPoint){
      //获取连接点所对应方法的签名信息
      Signature signature = joinPoint.getSignature();
      //获取连接点所对应方法的参数
      Object[] args = joinPoint.getArgs();
      System.out.println("LoggerAspect , 方法:"+signature.getName()+", 参数类型: "+ Arrays.toString(args));

    }

    @After("pointCut()")
    public void afterAdviceMethod(JoinPoint joinPoint){
        //获取连接点所对应方法的签名信息
        Signature signature = joinPoint.getSignature();
        //获取连接点所对应方法的参数
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect, 后置 , 方法: "+signature.getName()+", 参数类型: "+Arrays.toString(args));
    }

    /*
    * 在返回通知中若要获取目标对象方法的返回值
    * 只需要通过@AfterReturning注解中的returning属性
    * 就可以将通知方法的某个参数指定为接收目标对象方法的返回值的参数
    * */
    @AfterReturning( value = "pointCut()", returning = "result")
    public void afterReturningAdviceMethod( Object result){
        System.out.println("LoggerAspect , 返回通知 , 结果: "+result);
    }


    /*
     * 在异常通知中若要获取目标对象方法的异常
     * 只需要通过@AfterThrowing注解中的throwing属性
     * 就可以将通知方法的某个参数指定为接收目标对象方法出现的异常的参数
     * */
    @AfterThrowing(value = "pointCut()" , throwing = "ex")
    public void afterThrowingAdviceMethod( JoinPoint joinPoint , Throwable ex){
      //获取连接点对应方法的签名信息
        Signature signature = joinPoint.getSignature();
        System.out.println("LoggerAspect, 方法:"+signature.getName()+",异常通知  , 异常:"+ex);
    }


    @Around("pointCut()")
    //环绕通知的方法的返回值一定要和目标对象方法的返回值一致
    public Object aroundAdviceMethod(ProceedingJoinPoint proceedingJoinPoint){
        Object result = null;
        try {
            System.out.println("环绕通知-----前置通知");
            //表示目标对象方法的执行
           result= proceedingJoinPoint.proceed();
            System.out.println("环绕通知-----返回通知");
        } catch (Throwable e ) {
            e.printStackTrace();
            System.out.println("环绕通知-----异常通知");
        }finally {
            System.out.println("环绕通知-----后置通知");
        }
     return result;
    }
}

测试

package com.wfy.spring.annotation;

import com.wfy.aop.annotation.Calculator;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOPTest {

    @Test
    public void AopByAnnotationTest(){
        ApplicationContext ioc = new ClassPathXmlApplicationContext("aop-annotation.xml");
        Calculator bean = ioc.getBean(Calculator.class);
        bean.add(1,1);
    }
}

切面优先级

package com.wfy.aop.annotation;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Aspect//标识为一个切面
@Order(1)//设置切面的优先级,数字越小优先级越高
public class ValidateAspect {

    @Before("com.wfy.aop.annotation.LoggerAspect.pointCut()")
    public void beforeMethod(){
        System.out.println("ValidateAspect ---- 前置通知");
    }
}

标签:int,Spring,org,基础,annotation,result,使用,import,public
From: https://www.cnblogs.com/wfy-studying/p/16838717.html

相关文章

  • java基础-->数组
    **#数组介绍数组指的是一种容器,可以用来存储同种数据类型的多个值。数组容器在存储数据的时候,需要结合隐式转换考虑。下面写的都是一维数组,多维数组就是多个中括号即......
  • 不借助第三个变量,交换两个数。(使用异或^)
    packageclass02;importjava.util.Arrays;/***不借助第三个变量,交换两个数。(使用异或^)*异或(^):相同为0,不同为1。*记为:无进位相加。*/publicclassCod......
  • SpringMVC中文乱码
    <!--直接在web.xml中配置SpringMVC提供的过滤器注意url-pattern为 /*,过滤所有请求(包括jsp);如果设置为 /,访问jsp就不会经过过滤器了!--><filter><fi......
  • 在 MyBatis 中使用 <、<= 等特殊符号
    在实际的开发中,经常会遇到一些场景,比如查询小于某个时间,或者是查询小于某个年龄等。这个时候就需要在MyBatis的XML文件中使用一些>=、<=等符号,但是如果直接使用的话......
  • Emmet 使用详解
    title:Emmet语法使用详解date:2022-5-112:21:13index_img:img/post-img/html.jpgtags:[HTML,VScode]categories:软件配置Emmet使用详解初始化!,html:5......
  • 已知一个有序数组arr,和一个数字num。返回数组中是否含有这个数字。(使用二分法)
    packageclass01;importjava.util.Arrays;/***二分法*已知一个有序数组arr,和一个数字num。返回数组中是否含有这个数字。(使用二分法)*<p>*常规二分法的......
  • spring注解--切面(AOP)相关注解
    切面(AOP)相关注解Spring支持AspectJ的注解式切面编程。@Aspect声明一个切面(类上)使用@After、@Before、@Around定义建言(advice),可直接将拦截规则(切点)作为参数。@After在......
  • spring注解--@Bean的属性支持
    @Bean的属性支持@Scope设置Spring容器如何新建Bean实例(方法上,得有@Bean)其设置类型包括:·Singleton(单例,一个Spring容器中只有一个bean实例,默认模式),·Protetype(每......
  • 如何在html中引入DPlayer.js视频播放插件,以及任何使用DPlayer.js插件
    主要用到了实现了:视频播放 、监听开始、结束、暂停、播放时间、切换视频官方文档:http://dplayer.js.org github:https://github.com/whiskyma/gulp-demo截图如下:html......
  • vue3 基础-API-案例-ToDoList
    前面几篇我们介绍了compostionAPI的一些基础用法,如setup,ref,reactive,toRefs,toRef,context等.本篇呢找了一个经典的TodoList小案例来进行强化和巩固最......