博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring+Maven学习实验- Spring AOP面向切面编程(一)
阅读量:5216 次
发布时间:2019-06-14

本文共 9111 字,大约阅读时间需要 30 分钟。

Spring AOP 即 Aspect-oriented programming,面向切面编程,是作为面向对象编程的一种补充,专门用于处理系统中分布于各个模块(不同方法)中的交叉关注点的问题。简单地说,就是一个拦截器( interceptor )拦截一些处理过程。

例如,当一 个method 被执行,Spring AOP 能够劫持正在运行的 method ,在 method 执行前或者后加入一些额外的功能。

在 Spring AOP 中,支持 4 种类型的通知( Advice ):

  • Before advice - method 执行前通知
  • After returning advice - method 返回一个结果后通知
  • After throwing advice - method 抛出异常后通知
  • Around advice - 环绕通知,结合了以上三种        

下边这个例子解释 Spring AOP 怎样工作。首先一个简单的不使用 AOP 的例子。先创建一个简单的 Service ,为了稍后演示,这个类中加了几个简单的打印 method 。

1.pom.xml

4.0.0
com.shiyanlou.spring
aop
0.0.1-SNAPSHOT
jar
aop
http://maven.apache.org
UTF-8
junit
junit
3.8.1
test
org.springframework
spring-core
4.2.0.RELEASE
org.springframework
spring-context
4.2.0.RELEASE

2.CustomerService.java

package com.shiyanlou.spring.aop;public class CustomerService {    private String name;    private String url;        public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getUrl() {        return url;    }    public void setUrl(String url) {        this.url = url;    }        public void printName(){        System.out.println("Customer name:"+this.name);    }        public void printUrl(){        System.out.println("Customer url:"+this.url);    }        public void printThrowException() {        throw new IllegalArgumentException();    }}

3.SrpingAOP.xml

4.App.java

package com.shiyanlou.spring.aop;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {    public static void main( String[] args )    {        ApplicationContext appContext = new ClassPathXmlApplicationContext(                new String[]{"SpringAOP.xml"});        CustomerService cust = (CustomerService)appContext.getBean("customerService");        System.out.println("*************************");        cust.printName();        System.out.println("*************************");        cust.printUrl();              System.out.println("*************************");        try {            cust.printThrowException();        } catch (Exception e) {        }    }}

4 种类型的通知( Advice )

1.Before Advice

method 运行前,将运行下面的代码

HijackBeforeMethod.java 如下:

package com.shiyanlou.spring.aop;import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;public class HijackBeforeMethod implements MethodBeforeAdvice{    public void before(Method arg0, Object[] arg1, Object arg2)             throws Throwable {         System.out.println("HijackBeforeMethod : Before method hijacked!");            }}

在配置文件中加入新的 bean 配置 HijackBeforeMethod ,然后创建一个新的代理( proxy ),命名为 customerServiceProxy 。target 定义你想劫持哪个 bean; interceptorNames 定义想用哪个 class ( advice )劫持 target 。 ApringAOP.xml 如下:

hijackBeforeMethodBean

用 Spring proxy 之前,必须添加 CGLIB2 类库,,以下是 pom.xml 依赖:

org.glassfish.hk2.external
cglib
2.2.0-b23

app.java

package com.shiyanlou.spring.aop;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {    public static void main( String[] args )    {        ApplicationContext appContext = new ClassPathXmlApplicationContext(                new String[]{"SpringAOP.xml"});        CustomerService cust = (CustomerService)appContext.getBean("customerServiceProxy");        System.out.println("*************************");        cust.printName();        System.out.println("*************************");        cust.printUrl();              System.out.println("*************************");        try {            cust.printThrowException();        } catch (Exception e) {        }    }}

运行结果:

每一个 customerService 的 method 运行前,都将先执行 HijackBeforeMethod 的 before 方法。

2 After Returning Advice

创建一个实现了接口 AfterReturningAdvice 的 class ,method 运行后,直到返回结果后,才运行下边的代码,如果没有返回结果,将不运行切入的代码。

HijackAfterMethod.java 如下:

package com.shiyanlou.spring.aop;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice;public class HijackAfterMethod implements AfterReturningAdvice {    public void afterReturning(Object arg0, Method arg1, Object[] arg2,            Object arg3) throws Throwable {        System.out.println("After method hijack");    }}

SpringAOP.xml

hijackAfterMethodBean

App.java

package com.shiyanlou.spring.aop;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {    public static void main( String[] args )    {        ApplicationContext appContext = new ClassPathXmlApplicationContext(                new String[]{"SpringAOP.xml"});        CustomerService cust = (CustomerService)appContext.getBean("customerServiceProxy");        System.out.println("*************************");        cust.printName();        System.out.println("*************************");        cust.printUrl();              System.out.println("*************************");        try {            cust.printThrowException();        } catch (Exception e) {        }    }}

运行结果:

3 Afetr Throwing Advice

创建一个实现了 ThrowsAdvice 接口的 class ,劫持 IllegalArgumentException 异常,目标 method 运行时,抛出 IllegalArgumentException 异常后,运行切入的方法。HijackThrowException.java 如下:

package com.shiyanlou.spring.aop;import org.springframework.aop.ThrowsAdvice;public class HijackThrowException implements ThrowsAdvice {    public void afterThrowing(IllegalArgumentException e) throws Throwable {        System.out.println("HijackThrowException : Throw exception hijacked!");    }}

修改 bean 配置文件,加入了 hijackThrowExceptionBean ,ApringAdvice.xml 如下:

hijackThrowExceptionBean

运行结果:

4 Around Advice

结合了以上 3 种形式的 Advice ,创建一个实现了接口 MethodInterceptor 的 class ,你必须通过 methodInvocation.proceed() 来调用原来的方法,即通过调用 methodInvocation.proceed() 来调用 CustomerService 中的每一个方法,当然也可以不调用原方法 HijackAroundMethod.java 如下

package com.shiyanlou.spring.aop;import java.lang.reflect.Method;import java.util.Arrays;import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;public class HijackAroundMethod implements MethodInterceptor {    public Object invoke(MethodInvocation methodInvocation) throws Throwable {        System.out.println("Method name : "                + methodInvocation.getMethod().getName());        System.out.println("Method arguments : "                + Arrays.toString(methodInvocation.getArguments()));        // 相当于  MethodBeforeAdvice        System.out.println("HijackAroundMethod : Before method hijacked!");        try {            // 调用原方法,即调用CustomerService中的方法            Object result = methodInvocation.proceed();            // 相当于 AfterReturningAdvice            System.out.println("HijackAroundMethod : After method hijacked!");            return result;        } catch (IllegalArgumentException e) {            // 相当于 ThrowsAdvice            System.out.println("HijackAroundMethod : Throw exception hijacked!");            throw e;        }    }}

修改 bean 配置文件,加入了 hijackAroundMethodBean ,ApringAOP.xml如下:

hijackAroundMethodBean

运行app.java结果:

CustomerService 中每一个方法的调用,都会执行 HijackAroundMethod 中的 invoke 方法,可以看到整个切入点将目标 around 。

大多数的 Spring 开发者只用 Around Advice ,因为它能够实现所有类型的 Advice 。

在实际的项目开发中,我们还是要尽量选择适合的 Advice 。

在以上的例子中,CustomerService 中的所有方法都被自动拦截,但是大多数情况下,我们不需要拦截一个 class 中的所有方法,而是拦截符合条件的方法。

这时,我们就需要用到 Pointcut and Advice ,即切入点和通知

转载于:https://www.cnblogs.com/zoeyqq/p/6553612.html

你可能感兴趣的文章
20190422 T-SQL 触发器
查看>>
[置顶] Linux终端中使用上一命令减少键盘输入
查看>>
poj1422_有向图最小路径覆盖数
查看>>
BootScrap
查看>>
[大牛翻译系列]Hadoop(16)MapReduce 性能调优:优化数据序列化
查看>>
WEB_点击一百万次
查看>>
CodeForces - 878A Short Program(位运算)
查看>>
路冉的JavaScript学习笔记-2015年1月23日
查看>>
Mysql出现(10061)错误提示的暴力解决办法
查看>>
2018-2019-2 网络对抗技术 20165202 Exp3 免杀原理与实践
查看>>
NPM慢怎么办 - nrm切换资源镜像
查看>>
CoreData 从入门到精通(四)并发操作
查看>>
Swift - UIView的常用属性和常用方法总结
查看>>
Swift - 异步加载各网站的favicon图标,并在单元格中显示
查看>>
Java编程思想总结笔记Chapter 5
查看>>
[LeetCode]662. Maximum Width of Binary Tree判断树的宽度
查看>>
WinForm聊天室
查看>>
【Python学习笔记】1.基础知识
查看>>
梦断代码阅读笔记02
查看>>
selenium学习中遇到的问题
查看>>