• SpringAOP_构造注入实现


    SpringAOP_构造注入实现


    AOP_面向切面编程初步了解

    让我们先想象一个场景,你正在编写一个项目,在开发过程中的多个模块都有某段重复的代码,于是你选择将其抽象成一个方法,然后在需要的地方调用这个方法,当需要修改这段代码时只需要修改这个方法就行。有一天,你的Boss给了新的需求,需要再抽象出一个方法,然后再在各个需要这个方法的模块调用这个方法,这可能就让你头疼了,需要修改大量的代码,于是会想,能不能不修改源代码为系统业务添加某种功能呢?幸运的是,AOP可以很好的解决这个问题。

    简单介绍

    AOP:保证开发者不修改源代码的前提下,去为系统中的业务组件添加某种通用功能,本质是由AOP框架修改业务组件的多个方法的源代码,我们将其分为两类:

    • 静态AOP
      AOP 框架在编译阶段对程序源代码进行修改,生成了静态的 AOP 代理类(生成的*.class文件已经被改掉了,需要使用特定的编译器),比如 AspectJ。
    • 动态AOP:
      AOP 框架在运行阶段对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP。

    详细说明

    Spring 的通知类型

    名称 标签 说明
    前置通知 @Before 用于配置前置通知。指定增强的方法在切入点方法之前执行
    后置通知 @AfterReturning 用于配置后置通知。指定增强的方法在切入点方法之后执行
    环绕通知 @Around 用于配置环绕通知。指定增强的方法在切入点方法之前和之后都执行
    异常通知 @AfterThrowing 用于配置异常抛出通知。指定增强的方法在出现异常时执行
    最终通知 @After 用于配置最终通知。无论增强方式执行是否有异常都会执行
    切面类注解 @Aspect 标注该当前类是一个切面类
    断点注解 @Pointcut 使用一个返回值为 void 、方法体为空的方法来命名切入点

    实战演练

    导入依赖包

        <dependencies>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.3.5</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>5.3.5</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.6</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
            <dependency>
                <groupId>aopalliance</groupId>
                <artifactId>aopalliance</artifactId>
                <version>1.0</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
    

    创建一个增强类以及其接口

    增强类接口:

    public interface VisitService {
        //用于实现前置通知,后置通知,异常通知,最终通知
        void visit(String str) throws Exception;
    
        //用于实现环绕通知
        void around();
    }
    
    

    增强类:

    public class VisitServiceImpl implements VisitService {
        //前置,后置,最终,异常通知的增强类
        public void visit(String str) throws Exception{
            System.out.println(str);
            if(!str.equalsIgnoreCase("agree")){
                throw new Exception("非法访问");
            }
        }
        //环绕通知的增强类
        public void around() {
            System.out.println("环绕通知");
        }
    }
    

    创建一个切面类

    @Component("VisitAspect")
    @Aspect //标注当前myAspect是一个切面类
    public class VisitAspect_anno {
        // 定义切入点表达式
        // 使用一个返回值为 void 、方法体为空的方法来命名切入点
        @Pointcut("execution(* Spring_AOP.service.impl.VisitServiceImpl.visit(..))")
        private void v1() {
        }
    
        //前置通知
        @Before("v1()")
        public void visitBefore(JoinPoint joinPoint) {
    
            System.out.println("口令:");
        }
    
        @After("v1()")
        //最终通知,无论是否报错,都执行
        public void visitAfter(JoinPoint joinPoint) {
            System.out.println("输入完成");
        }
    
        @AfterReturning("v1()")
        //后置通知报错不执行
        public void visitSuccess(JoinPoint joinPoint) {
            System.out.println("请求成功,欢迎");
        }
    
        @AfterThrowing(value = "v1()",throwing = "ex")
        //异常通知,报错后执行
        public void visitThrow(JoinPoint joinPoint, Throwable ex) {
            System.out.println("请求失败,拒绝");
        }
    
        @Around("execution(* Spring_AOP.service.impl.VisitServiceImpl.around())")
        //环绕通知,如果报错只执行前一句
        public Object visitAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            System.out.println("-------环绕-------");
            Object obj = proceedingJoinPoint.proceed();
            System.out.println("------------------");
            return obj;
        }
    }
    
    

    配置xml文件

        <!-- 基于注解的声明式 AspectJ -->
        <context:component-scan base-package="Spring_AOP" />
        <!-- 启动基于注解的声明式 AspectJ 支持一 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    

    创建一个测试类

     public class visitTest {
        @Test
        public void VisitTest(){
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext_AOP.xml");
            VisitService visitService = app.getBean(VisitService.class);
            try {
                visitService.visit("agree");
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                visitService.visit("ok");
            } catch (Exception e) {
                e.printStackTrace();
            }
            visitService.around();
        }
    }
    

    测试运行

    口令:
    agree
    请求成功,欢迎
    输入完成
    口令:
    ok
    请求失败,拒绝
    输入完成
    -------环绕-------
    环绕通知
    -------环绕-------


    总结

    • 使用构造注入可以更方便的实现AOP模式,但是同样与设置注入相比各有千秋。

    以上就是以注解实现SpringAOP框架构造注入的实现,如有错误,麻烦指出,感谢耐心到现在的朋友ᕕ( ᐛ )ᕗ ---By 不断努力的Yang

  • 相关阅读:
    测试文档
    详细文档
    需求规格说明文档
    会议
    软工项目
    分组
    项目名
    google 常用的搜索关键词 (技术相关)
    Kafka 入门和 Spring Boot 集成
    用nginx实现分布式限流
  • 原文地址:https://www.cnblogs.com/LaChlanYang/p/14736950.html
Copyright © 2020-2023  润新知