场景描述:

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

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

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

  1. package concert;
  2.  
  3. import org.junit.Test;
  4. import org.junit.runner.RunWith;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.test.context.ContextConfiguration;
  7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  8.  
  9. @RunWith(SpringJUnit4ClassRunner.class)
  10. @ContextConfiguration(classes = concert.ConcertConfig.class)
  11. public class ConcertTest {
  12. @Autowired
  13. private Performance perform;
  14.  
  15. @Test
  16. public void test() {
  17. perform.perform();
  18. }
  19. }

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

5.结果

两种配置方式结果一样

笔记7 AOP练习<有疑问>的更多相关文章

  1. Spring笔记:AOP基础

    Spring笔记:AOP基础 AOP 引入AOP 面向对象的开发过程中,我们对软件开发进行抽象.分割成各个模块或对象.例如,我们对API抽象成三个模块,Controller.Service.Comma ...

  2. Spring学习笔记之aop动态代理(3)

    Spring学习笔记之aop动态代理(3) 1.0 静态代理模式的缺点: 1.在该系统中有多少的dao就的写多少的proxy,麻烦 2.如果目标接口有方法的改动,则proxy也需要改动. Person ...

  3. 笔记13 AOP中After和AfterReturning的区别

    AOP中 @Before @After @AfterThrowing@AfterReturning的执行顺序 public Object invoke(Object proxy, Method met ...

  4. 笔记9 AOP练习3(通过注解引入新功能 )

    切面可以为Spring bean添加新方法. 在Spring中,切面只是实现了它们所包装bean相同接口的 代理.如果除了实现这些接口,代理也能暴露新接口的话,会怎么样 呢?那样的话,切面所通知的be ...

  5. Spring笔记(三)AOP前篇之动态代理

    AOP思想是将程序中的业务代码与服务代码进行分离,在运行时进行结合.比较强调程序的层次结构,是一种面向切面的编程.而在AOP实现的底层主要用到了动态代理,而动态代理又分为JDK动态代理和CGLIB动态 ...

  6. Spring学习笔记之AOP配置篇(一)

    [TOC] 1. 创建并声明一个切面 首先,创建一个类,添加@Component注解使其添加到IoC容器 然后,添加@Aspect注解,使其成为一个切面 最后,在配置文件里面,使用<aop:as ...

  7. 笔记7 AOP

    1. 通知(Advice)   切面的工作被称为通知.通知定义了切面是什么以及何时使用.除了描述切面要完成的工作, 通知还解决了何时执行这个工作的问题.它应该应用在某个方法被调 用之前?之后?之前和之 ...

  8. Spring学习笔记4——AOP

    AOP 即 Aspect Oriented Program 面向切面编程 首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能. 所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务 ...

  9. [Spring学习笔记 4 ] AOP 概念原理以及java动态代理

    一.Spring IoC容器补充(1) Spring IoC容器,DI(依赖注入): 注入的方式:设值方法注入setter(属性注入)/构造子注入(构造函数传入依赖的对象)/字段注入Field(注解) ...

随机推荐

  1. 织梦cms网上复制图片不可用的解决方法

    背景描述: 织梦cms采集图片集时, 需要使用织梦cms提供的"网上复制图片"的功能, 好像我这里这个功能一直不可用, 今天下定决心研究了下源代码并进行了适当修改, 将我的修改提供 ...

  2. 17-TypeScript代理模式

    在有些情况下,我们需要把客户端真正调用的类和方法隐藏起来,而通过暴露代理类给客户端.客户端调用代理类的方式就可以访问到真实类提供的功能. abstract class Called{ protecte ...

  3. java:多层文件夹情况下,判断文件夹下是否有文件夹,并获取到没有文件夹的名字的方法

    业务问题案例 在公司遇到的一个问题,本以为很小很好解决,没想到花了一下午时间.图给的是文件路径,page1下有10个文件夹,每个有的有文件夹或者文件,要求得到page1下(即:123456789,10 ...

  4. RSA的公钥、私钥

    一.举个例子 1.发消息 用对方的公钥给对方发消息 2.发公告 发公告的时候,用自己的私钥形成签名! 二.加密和签名 RSA的公钥.私钥是互相对应的,RSA会生成两个密钥,你可以把任何一个用于公钥,然 ...

  5. spring-oauth-server实践:OAuth2.0 通过header 传递 access_token 验证

    一.解析查找 access_token 1.OAuth2AuthenticationProcessingFilter.tokenExtractor 2.发现来源可以有两处:请求的头或者请求的参数 二. ...

  6. Echarts 中国地图(包括china.js文件)

    用Echarts写中国地图需要导入china.js(现在官方不提供下载,个人找的在最下面有),根据需要的效果如下.位置可以自己在option里面修改 <!DOCTYPE html> < ...

  7. RxJava系列4(过滤操作符)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  8. Spring Boot面试题

    Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...

  9. Struts(十五):主题

    Theme主题是配置的struts-core.jar下的com.apache.struts2包下的default.properties中(默认配置为:xhtml) ### Standard UI th ...

  10. java集合详解

    1.java集合框架的层次结构 Collection接口: Set接口: HashSet具体类 LinkedHashSet具体类 TreeSet具体类 List接口:   ArrayList具体类 L ...