• 笔记7 AOP练习<有疑问>


    场景描述:

      核心业务:举行一场古典音乐会。

      周边功能:观众入场,关闭手机、落座,觉得音乐好听时鼓掌,觉都不好听则退票。(切面)

    1.编写切点(切点用于准确定位应该在什么地方应用切面的通 知)————即核心业务

    首先定义一个Performance接口:

    1 package concert;
    2 
    3 public interface Performance {
    4     public void perform();
    5 }

    2.定义切面,即编写Audience.java。

    Audience类使用@Aspect注解进行了标注。该注解表明Audience不仅仅是一个POJO,还是一个切面。

    @Pointcut注解能够在一 个切面内定义可重用的切点。

    也可以在通知注解中直接使用切点表达式。

     1 package concert;
     2 
     3 import org.aspectj.lang.annotation.AfterReturning;
     4 import org.aspectj.lang.annotation.AfterThrowing;
     5 import org.aspectj.lang.annotation.Aspect;
     6 import org.aspectj.lang.annotation.Before;
     7 import org.aspectj.lang.annotation.Pointcut;
     8 import org.springframework.stereotype.Component;
     9 
    10 @Aspect
    11 @Component
    12 public class Audience {
    13     @Pointcut("execution(** concert.Performance.perform(..))")
    14     public void perform() {
    15 
    16     }
    17 
    18     // @Before("execution(** concert.Performance.perform(..))")
    19     @Before("perform()")
    20     public void silenceCellPhones() {
    21         System.out.println("Silencing cell phone");
    22     }
    23 
    24     // @Before("execution(** concert.Performance.perform(..))")
    25     @Before("perform()")
    26     public void takeSeats() {
    27         System.out.println("Taking seats");
    28     }
    29 
    30     // @AfterReturning("execution(** concert.Performance.perform(..))")
    31     @AfterReturning("perform()")
    32     public void applause() {
    33         System.out.println("CLAP CLAP CLAP");
    34     }
    35 
    36     // @AfterThrowing("execution(** concert.Performance.perform(..))")
    37     @AfterThrowing("perform()")
    38     public void demandRefund() {
    39         System.out.println("Demanding a refund");
    40     }
    41 }

    Audience有四个方法,定义了一个观众在观看演出时可能会做的事 情。在演出之前,观众要就坐(takeSeats())并将手机调至静音 状态(silenceCellPhones())。如果演出很精彩的话,观众应 该会鼓掌喝彩(applause())。不过,如果演出没有达到观众预期 的话,观众会要求退款(demandRefund())。 这些方法都使用了通知注解来表明它们应该在什么时候调用。

    在这里也可以使用环绕通知,环绕通知是最为强大的通知类型。它能够让你所编写的逻辑将被通知 的目标方法完全包装起来。实际上就像在一个通知方法中同时编写前 置通知和后置通知,代码如下:

     1      @Around("performs()") // 环绕通知方法
     2      public void watchPerformance(ProceedingJoinPoint jp) {
     3      try {
     4      System.out.println("Silencing cell phone");
     5      System.out.println("Taking seats");
     6      jp.proceed();
     7      System.out.println("CLAP CLAP CLAP");
     8      } catch (Throwable e) {
     9      System.out.println("Demanding a refund");
    10      }
    11      }

    在这里,@Around注解表明watchPerformance()方法会作 为performance()切点的环绕通知。ProceedingJoinPoint作为参数。这个对象是必须要有的,因为要在通知中通过它来调用被通知的方法。通知方法中可以做任何的 事情,当要将控制权交给被通知的方法时,它需要调 用ProceedingJoinPoint的proceed()方法。 

    <可以不调用proceed()方法,从而阻塞对被通知方 法的访问,与之类似,也可以在通知中对它进行多次调用。要这样 做的一个场景就是实现重试逻辑,也就是在被通知方法失败后,进行 重复尝试。>

    3.定义Java配置文件ConcertConfig.java,使用Spring自动装配。在Java配置文件中启用AspectJ注解的自动代理。

    AspectJ自动代理都会为使 用@Aspect注解的bean创建一个代理,这个代理会围绕着所有该切面 的切点所匹配的bean。

     1 package concert;
     2 
     3 import org.springframework.context.annotation.ComponentScan;
     4 import org.springframework.context.annotation.Configuration;
     5 import org.springframework.context.annotation.EnableAspectJAutoProxy;
     6 
     7 @Configuration
     8 @EnableAspectJAutoProxy // 启用AspectJ自动代理
     9 @ComponentScan
    10 public class ConcertConfig {
    11 
    12 }

    也可以定义XML配置文件

    在Spring中要使用XML来装配bean的话,那么需要使用Spring aop命名空间中的<aop:aspectj-autoproxy>元素启用自动代理。

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:aop="http://www.springframework.org/schema/aop"
     5     xmlns:tx="http://www.springframework.org/schema/tx"
     6     xmlns:context="http://www.springframework.org/schema/context"
     7     xmlns:c="http://www.springframework.org/schema/c"
     8     xsi:schemaLocation="
     9    http://www.springframework.org/schema/beans
    10    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    11    http://www.springframework.org/schema/aop
    12    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    13    http://www.springframework.org/schema/tx
    14    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    15    http://www.springframework.org/schema/context     
    16    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    17           <context:component-scan base-package="concert"></context:component-scan>
    18           <aop:aspectj-autoproxy></aop:aspectj-autoproxy>   <!--启用自动代理-->
    19          <!-- <bean class="concert.Audience"></bean>
    20           <bean class="concert.Classcial"></bean>   -->
    21    </beans>

     注:在使用XML进行装配的时候,如果在XML声明了bean后,一定要去掉两个bean原来的@Component注解,且不用使用自动代理;如果不在XML文件中声明bean,在Audience和Classcial中添加@Component注解,则可以启用自动代理。

    4.编写测试文件ConcertTest.java

    package concert;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = concert.ConcertConfig.class)
    public class ConcertTest {
        @Autowired
        private Performance perform;
    
        @Test
        public void test() {
            perform.perform();
        }
    }

    疑问:在进行测试时,只能定义接口的对象来进行测试,定义接口的实现类对象时就会报错。

    5.结果

    两种配置方式结果一样

  • 相关阅读:
    windows +xampp+wordpress
    IP 包类型
    [二叉树]已知后序/中序遍历,求先序遍历
    QT 设置应用程序图标
    Nginx 优化 Alex
    编译安装REDIS Alex
    Http简介 Alex
    Nginx调试 Alex
    利用私有CA 给内部https网站颁发证书 Alex
    实现https安全网站之自签名证书 Alex
  • 原文地址:https://www.cnblogs.com/lyj-gyq/p/8881594.html
Copyright © 2020-2023  润新知