最近在翻《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. Android的事件处理机制之基于回调的事件处理

    回调机制 如果说事件监听机制是一种委托式的事件处理,那么回调机制则与之相反,对于基于回调的事件处理模型来说,事件源与事件监听器是统一的,换种方法说事件监听器完全消失了,当用户在GUI组件上激发某个事件 ...

  2. [转]Android 如何建立AIDL

    建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下: (1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件.该文件的语法类似于Java代码,但会稍有不同.详 ...

  3. Day8 - D - Multiplication Table CodeForces - 448D

    Bizon the Champion isn't just charming, he also is very smart. While some of us were learning the mu ...

  4. SpringBoot-数据库连接信息配置

    SpringBoot-数据库连接信息配置 SpringBoot-数据库连接信息配置 ​ 在SpringBoot中提供了默认的数据库连接器-追光者HikariCP,我们只需要添加jdbc的启动器就会自动 ...

  5. centos7安装google-chrome和chromedriver

    1.root用户下进入到etc/yum.repos.d目录下  [root@f7d6b9f2-1291-4d2f-8805-aef94deac9f7 yum.repos.d]# pwd  /etc/y ...

  6. 批处理+7zip解压用纯数字加密的压缩包zip

    @echo off set path=c:\Program Files\7-Zip; for /L %%i in (0,1,100000) do ( call :myfunc %%i ) goto : ...

  7. 项目中常用的JS操作技巧

    1.<a>标签-超链接中confirm方法使用介绍 <a href="a.html" onclick="if(confirm('确定删除?')==fal ...

  8. Web系统测试的常用方法总结-18《转载》

    Web系统测试的常用方法归纳 --- 知识记录 1.页面链接检查 每一个链接是否都有对应的页面,并且页面之间切换正确.可以依靠一些工具,如:LinkBotPro.File-AIDCS.HTML Lin ...

  9. python3调用微软js引擎ChakraCore

    有关ChakraCore介绍请移步:https://github.com/Microsoft/ChakraCore 使用案例GitHub源码:https://github.com/pyAppman/C ...

  10. 二十二、JavaScript之在对象中写函数

    一.代码如下 二.效果如下 <!DOCTYPE html> <html> <meta http-equiv="Content-Type" conten ...