首先我们先来介绍一下AOP:

  AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充。

  面向对象编程是从静态角度考虑程序的结构,面向切面编程是从动态的角度考虑程序运行过程。

  AOP底层,就是采用动态代理模式实现的。采用两种代理:JDK的动态代理,与CGLIB的动态代理。

  JDK的动态代理是面向接口的,CGLIB既可以实现有接口的,又可以实现没有接口的。(对动态代理不了解的可以看看我的其关于动态代理的介绍)

  面向切面编程,就是将交叉业务逻辑封装成切面,利用AOP容器的功能将切面植入到主业务逻辑中。所谓交叉业务逻辑是指:通用的,与主业务逻辑无关的代码,如安全检查,事务日志等。

Spring的AOP的几种用法:

通知:即我们的切面方法

  1. 前置通知
  2. 后置通知
  3. 环绕通知
  4. 异常通知

(一)前置通知 
  所谓前置通知,就是这个切面方法在我们的主业务方法之前执行。

首先我们先写一个目标接口:

//目标接口
public interface SomeServices {String doFirst();void doSecond();
}

//接口实现类,也就是主业务方法类
public class SomeServiceImp implements SomeServices{@Overridepublic String doFirst() {System.out.println("print first");return null;}@Overridepublic void doSecond() {System.out.println("print second");}
}

//切面方法,需要实现:**MethodBeforeAdvice** 接口
public class myBeforeMethodAdvice implements MethodBeforeAdvice {//method:业务方法//args:方法参数//target:目标类
    @Overridepublic void before(Method method, Object[] arg1, Object target) throws Throwable {System.out.println("执行主业务前方法");}}

<!--Spring主配置文件--><bean id="service" class="com.test.beforeMethodAdvice.SomeServiceImp"/><bean id="myAdvice" class="com.test.beforeMethodAdvice.myBeforeMethodAdvice"/><bean id="ProxyService" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="service"/><!--<property name="target" value="service"/>--><property name="interceptorNames" value="myAdvice"/></bean>

接着是测试方法:

public class test {@Testpublic void Test01() {String source = "com/test/beforeMethodAdvice/applicationContext.xml";ApplicationContext ac = new ClassPathXmlApplicationContext(source);SomeServices service = (SomeServices)ac.getBean("ProxyService");service.doFirst();service.doSecond();}
}
//控制台输出:
//执行主业务前方法
//print first
//执行主业务前方法
//print second

(二)后置通知 

  后置通知和前置通知雷同,只是切面方法的实现类不同,但是后置通知实现接口方法,多给用了一个returnValue参数,也就意味着我们可以获得主业务方法的返回值,我们来看看范例:

//主业务接口
public interface SomeServices {String doFirst();void doSecond();
}

//主业务方法实现类,doFirst()有返回值
package com.test.afterMethodAdvice;public class SomeServiceImp implements SomeServices{@Overridepublic String doFirst() {System.out.println("print first");return "abc";}@Overridepublic void doSecond() {System.out.println("print second");}
}

//实现了**AfterReturningAdvice** 接口,实现这个接口的方法有一个返回值参数
public class myAfterMethodAdvice implements AfterReturningAdvice {//returnValue:业务方法的返回值//method:业务方法属性类//args:方法参数//target:目标类
    @Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println("执行业务后方法");//只能获取到业务方法的返回值,但是不能进行修改
        System.out.println(returnValue);}

<!--配置文件没什么差别--><bean id="service" class="com.test.afterMethodAdvice.SomeServiceImp"/><bean id="myAdvice" class="com.test.afterMethodAdvice.myAfterMethodAdvice"/><bean id="ProxyService" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="service"/><!--<property name="targetName" value="service"/>--><property name="interceptorNames" value="myAdvice"/></bean>

测试方法:

public class test {@Testpublic void Test01() {String source = "com/test/afterMethodAdvice/applicationContext.xml";ApplicationContext ac = new ClassPathXmlApplicationContext(source);SomeServices service = (SomeServices)ac.getBean("ProxyService");service.doFirst();service.doSecond();}
}
//print first
//执行业务后方法
//abc
//print second
//执行业务后方法
//null

(三)环绕通知

  环绕通知就是既能实现前置通知又能实现后置通知,但是不同的是它能够对主业务方法进行修改。

//主业务接口
public interface SomeServices {String doFirst();void doSecond();
}

//主业务方法实现类
public class SomeServiceImp implements SomeServices{@Overridepublic String doFirst() {System.out.println("print first");return "abc";}@Overridepublic void doSecond() {System.out.println("print second");}
}

//环绕通知,切面方法类,需要实现**MethodInterceptor**
//并且调用参数的proceed方法,这个方法有一个返回值,也就是主业务方法的返回值,我们可以对它进行修改。
public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("环绕通知,业务方法前");Object result = invocation.proceed();System.out.println("环绕通知,业务方法后");if(result != null) {result = ((String)result).toUpperCase();}return result;}
}

//环绕通知的配置文件
<bean id="service" class="com.test.MethodInterceptor.SomeServiceImp"/><bean id="myAdvice" class="com.test.MethodInterceptor.MyMethodInterceptor"/><bean id="ProxyService" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="service"/><property name="interceptorNames" value="myAdvice"/></bean>

//测试方法:
public class test {@Testpublic void Test01() {String source = "com/test/MethodInterceptor/applicationContext.xml";ApplicationContext ac = new ClassPathXmlApplicationContext(source);SomeServices service = (SomeServices)ac.getBean("ProxyService");String result = service.doFirst();System.out.println(result);service.doSecond();}
}
//控制台输出:
//环绕通知,业务方法前
//print first
//环绕通知,业务方法后
//ABC
//环绕通知,业务方法前
//print second
//环绕通知,业务方法后

(四)异常通知

  异常通知就是当我们的主业务方法出现异常的时候,会对这个主业务方法进行加强!

  例如:我们现在的主业务方法是对用户名和密码进行判断,如果用户名或者密码有误,我们就就分别抛出对应的错误,当无误的时候,程序正常执行。

//主业务接口,判断用户名,密码是否正确
public interface SomeServices {boolean checkedUser(String username,String password) throws UserException;
}

//实现类,实现了对用户和密码的校验
public class SomeServiceImp implements SomeServices{@Overridepublic boolean checkedUser(String username, String password)throws UserException {if(!"admin".equals(username.trim())) {throw new UsernameException("用户名错误");}if(!"123".equals(password.trim())){throw new PasswordException("密码错误");}return true;}
}

上面两个是我们需要的主业务方法,里面我们定义了两个异常:UsernameException,PasswordException,它们都实现了父类UserException:

//UserException
public class UserException extends Exception {public UserException() {super();}public UserException(String message) {super(message);}
}

//UsernameException
public class UsernameException extends UserException {public UsernameException() {super();}public UsernameException(String message) {super(message);}
}

//PasswordException
public class PasswordException extends UserException {public PasswordException() {super();}public PasswordException(String message) {super(message);}}

定义好上面的异常后我们就要定义我们的通知类了:

//这个异常通知需要实现ThrowsAdvice接口,接口源码上面有,我们追踪到源码会发现这个接口没有需要实现的方法,其实是由几个供我们选择,防止我们没有必要的实现全部方法public class MyThrowsAdvice implements ThrowsAdvice {public void afterThrowing(Exception ex) {System.out.println("执行异常通知方法:" + ex.getMessage());}
}

配置文件没有什么变化:

<bean id="service" class="com.test.afterExceptionAdvice.SomeServiceImp"/><bean id="myAdvice" class="com.test.afterExceptionAdvice.MyThrowsAdvice"/><bean id="ProxyService" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="service"/><property name="interceptorNames" value="myAdvice"/></bean>

最后就是我们的测试方法:

public class test {@Testpublic void Test01()  {String source = "com/test/afterExceptionAdvice/applicationContext.xml";ApplicationContext ac = new ClassPathXmlApplicationContext(source);SomeServices service = (SomeServices)ac.getBean("ProxyService");//service.checkedUser("admin", "123");//service.checkedUser("ad", "123");try {service.checkedUser("admin", "12");} catch (UserException e) {e.printStackTrace();}}
}
//控制台:
//**报错**
//执行异常通知方法:密码错误

本篇文章可能主要是代码的实现,原理上没有说的太多,因为前面关于动态代理的文章我也写了一篇,所以这里就没有赘述太多动态代理的知识。

版权声明:本文为博主原创文章,如需转载请表明出处。 https://blog.csdn.net/qq_39266910/article/details/78742552

转载于:https://www.cnblogs.com/chengshun/p/9776849.html

08 Spring框架 AOP (一)相关推荐

  1. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  2. Spring框架AOP源码剖析

    今天我要和大家分享的是 AOP(Aspect-Oriented Programming)这个东西的源码剖析,作为多年的开发者,想必大家在面试的时候都被问过,你知道Spring框架AOP的底层实现机制吗 ...

  3. Spring框架 AOP面向切面编程(转)

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  4. Spring框架----AOP的概念及术语

    1.什么是AOP AOP:全称是 Aspect Oriented Programming 即:面向切面编程 简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源 ...

  5. Spring框架-AOP

    1.什么是AOP? 面向切面编程,可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率 通过不修改源代码方式,在主干功能里面添加新功能 2 ...

  6. Spring框架——AOP入门笔记以及个人总结

    注:作者本人也是初学者,所以本文有些总结性见解可能存在问题,但是多数问题都是在上网查询过资料后总结的,如果有逻辑或者原理上的错误,或者见解不同,欢迎在评论区讨论!!! 目录 Spring的AOP 1. ...

  7. spring框架AOP的理解,程序高类聚的体现

    本文主要介绍AOP思想,而不是Spring,Spring在本文只做为理解AOP的工具和例子,所以也不打算介绍Spring的Aspect.Join point.Advice.AOP proxy等概念,那 ...

  8. Spring框架AOP原理及实现

    1.AOP思想 1.1 什么是AOP Aspect oritention programming(面向切面编程),把一个个的横切关注点(这些零散存在于业务方法中的功能代码,我们称之为横切面关注点)放到 ...

  9. Spring 框架 AOP 的总结

    一:帝国之军-AOP 1:案例分析 ![事务案例](https://img-blog.csdn.net/2018040518063398?watermark/2/text/aHR0cHM6Ly9ibG ...

最新文章

  1. 想学图像分割,强烈建议从这5篇图像分割算法综述
  2. kafka(一)-为什么使用kafka
  3. CentOS 7设置KVM硬盘模式为SCSI
  4. LeetCode 22. 括号生成(Generate Parentheses)
  5. oracle change schema,使用pt-online-schema-change修改主键时注意
  6. 软件测试的目标及组织测试过程
  7. Spark修炼之道(高级篇)——Spark源码阅读:第九节 Task执行成功时的结果处理...
  8. [Python] L1-013. 计算阶乘和-PAT团体程序设计天梯赛GPLT
  9. 【NOIP2017】【Luogu3954】成绩(模拟)
  10. Oracel 格式化日期 to_char()
  11. 服务器虚拟机要怎么安装,服务器虚拟机怎么安装
  12. Notepad JSON格式化
  13. CSDN博客编写快捷键
  14. python中forward是什么意思_pytorch 调用forward 的具体流程
  15. Android M及以上版本系统 悬浮窗权限 的解决方案
  16. 华为GaussDB数据库10个知识点,第7个你知道么?
  17. 小程序源码:网课查题微信小程序源码下载,题库资源丰富自动采集,支持语音拍照识别
  18. linux查询服务器cpu核数_查看linux服务器CPU数量
  19. WebUploader重复多次上传问题
  20. 迅雷向链享云售让部分区块链业务:包括链克与链克商城

热门文章

  1. springcloud服务注册和发现
  2. A - Beautiful Matrix
  3. 《Effective Java》读书笔记 - 5.泛型
  4. Python练习-从小就背不下来的99乘法表
  5. ASP渲染下拉框使时间依次减少
  6. BZOJ4562: [Haoi2016]食物链
  7. 【原】.Net创建Excel文件(插入数据、修改格式、生成图表)的方法
  8. mysql 半同步关闭_MySQL的半同步模式配置
  9. 8k分辨率需要多大带宽_又一支持8K分辨率的接口标准发布
  10. python define function的顺序_Python怎么根据一个函数来决定列表顺序