最近在翻《Spring In Action》Spring 实战这本书,重新了解了一下AOP的概念和思想并写了一个小Demo示例,记录在这里:

环境:intelliJ IDEA 2018、MAVEN管理依赖

一:项目的POM文件内容:

<?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.cmhit.springinaction</groupId>
<artifactId>Chapter3</artifactId>
<version>1.0-SNAPSHOT</version> <dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency> <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.5.RELEASE</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies> </project>

pom.xml

二:创建包来容纳用到的类文件:

三:创建接口类Performance,该类仅有一个perform方法:

package concert;

public interface Performance {
public void perform();
}

Performance.java

四:创建接口的实现类Movie

package concert;

import org.springframework.stereotype.Component;

@Component
public class Movie implements Performance {
public void perform(){
System.out.println("The movie is showing");
};
}

Movie.java

五:定义一个“观众”切面:

package concert;

import org.aspectj.lang.annotation.*;

@Aspect
public class Audience {
@Pointcut("execution( * concert.Performance.perform(..))")
public void performance(){} @Before("performance()")
public void silenceCellPhones(){
System.out.println("Silencing cell phones");
} @Before("performance()")
public void takeSeats(){
System.out.println("Taking seats");
} @AfterReturning("performance()")
public void applause(){
System.out.println("CLAP CLAP CLAP");
} @AfterThrowing("performance()")
public void demandRefund(){
System.out.println("Demanding a refund");
}
}

Audience.java

六:至此,基本的类都已经建立完毕了,下面创建配置类将它们装配起来:

package concert;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "concert")
public class appConfig {
@Bean
public Performance movie() {
return new Movie();
} @Bean
public Audience audience(){
return new Audience();
}
}

appConfig

七:在test目录下面建立相同的package,并创建测试类:

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 = appConfig.class)
public class TestConcert {
@Autowired
private Performance perform; @Test
public void test01(){
perform.perform();
}
}

TestConcert

八:测试运行结果:

九:根据上面的demo,再次加深理解AOP的几个概念:通知、连接点、切点、切面、织入

通知:通知定义了切面要完成的工作以及在什么时候使用,上面的demo中,表演前的手机静音,表演前观众入座,表演成功结束后的鼓掌,表演失败后观众要求退票,这其中的每一项都是通知,通知可以分为前置通知(目标方法调用前执行),后置通知(方法完成后执行,且不管方法的输出是什么),返回通知(方法成功执行后调用通知),异常通知(方法执行发生异常时调用通知),环绕通知(通知包裹了被通知的方法,效果类似方法调用前后均调用,但是环绕通知可以将所有的通知方法放在一起);

连接点:连接点是应用执行过程中能插入到切面的点,这个点可以是方法被调用,抛出异常或者是属性被修改,切面的代码就是利用这些连接点将代码插入到应用程序的正常流程中,上面demo中的perform方法就是一个连接点;

切点:应用程序中存在数以千计的连接点,我们的切面程序代码不一定要插入到所有的连接点中,那些切面织入的连接点集合就是切点。

切面:切面是通知和切点的集合,即切面描述了需要做什么工作(手机静音、就坐、鼓掌、退票),在什么时候工作(perform方法执行前还是执行后,还是发生异常时),在哪些地方执行工作。

织入:将切面在指定的连接点织入到目标对象中的过程就是织入,织入的基本原理是创建原对象的代理对象,所有在原对象上的方法调用均会被代理对象拦截(代理类封装了目标类),在执行完切面逻辑代码后,再将调用转给真正的目标bean。

补充:可以使用环绕通知重写上面的audience类:

package concert;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; @Aspect
public class Audience { @Pointcut("execution( * concert.Performance.perform(..))")
public void performance(){} @Around("performance()")
public void watchPerformance(ProceedingJoinPoint jp){
try {
System.out.println("Silencing cell phones");
System.out.println("Taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP");
}catch (Throwable e){
System.out.println("Demanding a refund");
}
}
}

Audience.java

执行的效果和上面是一样的,代码中的ProceedingJoinPoint对象用来控制被通知方法的调用:jp.proceed(),如果不调用这个方法,可以实现阻塞被通知方法(performance)的调用,而且可以反复调用jp.proceed(),相当于反复调用perform()方法。

Spring AOP复习的更多相关文章

  1. Spring AOP 复习

    Aspect Oriented Programming 通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,利用aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降 ...

  2. Spring技术内幕:Spring AOP的实现原理(二)

    **二.AOP的设计与实现 1.JVM的动态代理特性** 在Spring AOP实现中, 使用的核心技术时动态代理.而这样的动态代理实际上是JDK的一个特性.通过JDK的动态代理特性,能够为随意Jav ...

  3. Spring AOP 和 AspectJ

    现如今有许多个可用的 AOP 库,使用这些库需要能够回答以下问题: 是否与现有的或新的应用程序兼容? 在哪里可以使用 AOP ? 如何迅速与应用程序集成? 性能开销是多少? 在本文中,我们将回答这些问 ...

  4. Spring知识点复习

    Spring知识点复习 一.专业术语 侵入式设计 引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类.如:Struts框架 非侵入式设计 引入框架,对现有的类结构没有影响.如:Hiberna ...

  5. 运用Spring Aop,一个注解实现日志记录

    运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...

  6. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  7. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  8. spring aop

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将 ...

  9. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

随机推荐

  1. CentOS configuration uses the SFTP server

    SFTP,即 SSH 文件传输协议( SSH File Transfer Protocol ),或者说是安全文件传输协议( Secure File Transfer Protocol ).SFTP 是 ...

  2. 安装ruby的一些坑

    之前一直下载不下来.是因为需要翻墙.

  3. HTML速写

    1. E 代表HTML标签. 2. E#id 代表id属性. 3. E.class 代表class属性. 4. E[attr=foo] 代表某一个特定属性. 5. E{foo} 代表标签包含的内容是f ...

  4. 059、Java中定义一个有参数无返回值的方法

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  5. 011、MySQL取14天前Unix时间戳

    #取14天前时间戳 SELECT unix_timestamp( DATE_SUB( curdate( ), INTERVAL DAY ) ); 效果如下: 不忘初心,如果您认为这篇文章有价值,认同作 ...

  6. 数据结构——Java Stack 类

    定义 栈是Vector的一个子类,它实现了一个标准的后进先出的栈.堆栈只定义了默认构造函数,用来创建一个空栈. 堆栈除了包括由Vector定义的所有方法,也定义了自己的一些方法. 图例 在下面图片中可 ...

  7. pyhton读入Excel和csv数据文件

    pyhton读入Excel和csv数据文件#file 数据文件的输入输出操作(主要包括Excel表格和csv表格文件)import pandas as pd #pyhton读入数据必须要导入panda ...

  8. day09 Django: 组件cookie session

    day09 Django: 组件cookie session   一.cookie和session都是会话跟踪技术     1.什么是会话             可以理解为客户端和服务端之间的一次会 ...

  9. Golang的运算符优先级实操案例

    Golang的运算符优先级实操案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.运算符优先级案例 运算符是用来在程序运行时执行数学或逻辑运算的,在Go语言中,一个表达式可以包 ...

  10. P1083 是否存在相等的差

    P1083 是否存在相等的差 转跳点: