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

一 AOP的基本概念

(1)Aspect(切面):通常是一个类,里面可以定义切入点和通知

(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用

(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around

(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式

(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类

二 Spring AOP

Spring中的AOP代理还是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理,不过现在的项目都是面向接口编程,所以JDK动态代理相对来说用的还是多一些。

三 基于注解的AOP配置方式

1.启用@AsjectJ支持

在applicationContext.xml中配置下面一句:

<aop:aspectj-autoproxy />

2.通知类型介绍

(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可

(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值

(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名

来访问目标方法中所抛出的异常对象

(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式

(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint

3.例子:

(1)Operator.java --> 切面类

@Component
@Aspect
public class Operator {@Pointcut("execution(* com.aijava.springcode.service..*.*(..))")public void pointCut(){}@Before("pointCut()")public void doBefore(JoinPoint joinPoint){System.out.println("AOP Before Advice...");}@After("pointCut()")public void doAfter(JoinPoint joinPoint){System.out.println("AOP After Advice...");}@AfterReturning(pointcut="pointCut()",returning="returnVal")public void afterReturn(JoinPoint joinPoint,Object returnVal){System.out.println("AOP AfterReturning Advice:" + returnVal);}@AfterThrowing(pointcut="pointCut()",throwing="error")public void afterThrowing(JoinPoint joinPoint,Throwable error){System.out.println("AOP AfterThrowing Advice..." + error);System.out.println("AfterThrowing...");}@Around("pointCut()")public void around(ProceedingJoinPoint pjp){System.out.println("AOP Aronud before...");try {pjp.proceed();} catch (Throwable e) {e.printStackTrace();}System.out.println("AOP Aronud after...");}}

(2)UserService.java --> 定义一些目标方法

@Service
public class UserService {public void add(){System.out.println("UserService add()");}public boolean delete(){System.out.println("UserService delete()");return true;}public void edit(){System.out.println("UserService edit()");int i = 5/0;}}

(3).applicationContext.xml

<context:component-scan base-package="com.aijava.springcode"/><aop:aspectj-autoproxy />

(4).Test.java

public class Test {public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");UserService userService = (UserService) ctx.getBean("userService");userService.add();}
}

上面是一个比较简单的测试,基本涵盖了各种增强定义。注意:做环绕通知的时候,调用ProceedingJoinPoint的proceed()方法才会执行目标方法。

4.通知执行的优先级

进入目标方法时,先织入Around,再织入Before,退出目标方法时,先织入Around,再织入AfterReturning,最后才织入After。

注意:Spring AOP的环绕通知会影响到AfterThrowing通知的运行,不要同时使用!同时使用也没啥意义。

5.切入点的定义和表达式

切入点表达式的定义算是整个AOP中的核心,有一套自己的规范

Spring AOP支持的切入点指示符:

(1)execution:用来匹配执行方法的连接点

A:@Pointcut("execution(* com.aijava.springcode.service..*.*(..))")

第一个*表示匹配任意的方法返回值,..(两个点)表示零个或多个,上面的第一个..表示service包及其子包,第二个*表示所有类,第三个*表示所有方法,第二个..表示

方法的任意参数个数

B:@Pointcut("within(com.aijava.springcode.service.*)")

within限定匹配方法的连接点,上面的就是表示匹配service包下的任意连接点

C:@Pointcut("this(com.aijava.springcode.service.UserService)")

this用来限定AOP代理必须是指定类型的实例,如上,指定了一个特定的实例,就是UserService

D:@Pointcut("bean(userService)")

bean也是非常常用的,bean可以指定IOC容器中的bean的名称

6.基于XML形式的配置方式

开发中如果选用XML配置方式,通常就是POJO+XML来开发AOP,大同小异,无非就是在XML文件中写切入点表达式和通知类型

例子:

(1)Log.java

public class Log {private Integer id;//操作名称,方法名private String operName;//操作人private String operator;//操作参数private String operParams;//操作结果 成功/失败private String operResult;//结果消息private String resultMsg;//操作时间private Date operTime = new Date();setter,getter}

(2).Logger.java

/*** 日志记录器 (AOP日志通知)*/
public class Logger {@Resourceprivate LogService logService;public Object record(ProceedingJoinPoint pjp){Log log = new Log();try {log.setOperator("admin");String mname = pjp.getSignature().getName();log.setOperName(mname);//方法参数,本例中是User userObject[] args = pjp.getArgs();log.setOperParams(Arrays.toString(args));//执行目标方法,返回的是目标方法的返回值,本例中 voidObject obj = pjp.proceed();if(obj != null){log.setResultMsg(obj.toString());}else{log.setResultMsg(null);}log.setOperResult("success");log.setOperTime(new Date());return obj;} catch (Throwable e) {log.setOperResult("failure");log.setResultMsg(e.getMessage());} finally{logService.saveLog(log);}return null;}
}

(3).applicationContext.xml

<aop:config><aop:aspect id="loggerAspect" ref="logger"><aop:around method="record" pointcut="(execution(* com.aijava.distributed.ssh.service..*.add*(..))or   execution(* com.aijava.distributed.ssh.service..*.update*(..))or   execution(* com.aijava.distributed.ssh.service..*.delete*(..)))and !bean(logService)"/></aop:aspect>
</aop:config>

注意切入点表达式,!bean(logService) 做日志通知的时候,不要给日志本身做日志,否则会造成无限循环!

有关更详细的Spring AOP知识,可以查看Spring官方文档第9章Aspect Oriented Programming with Spring

7.JDK动态代理介绍

例子:

(1)UserService.java

public interface UserService {public void add();
}

(2)UserServiceImpl.java

public class UserServiceImpl implements UserService{public void add() {System.out.println("User add()...");}}

(3)ProxyUtils.java

public class ProxyUtils implements InvocationHandler{private Object target;public ProxyUtils(Object target){this.target = target;}public Object getTarget() {return target;}public void setTarget(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("do sth before...");method.invoke(target, args);System.out.println("do sth after...");return null;}}

(4)Test.java

public class Test {public static void main(String[] args) {UserService userService = new UserServiceImpl();ProxyUtils proxyUtils = new ProxyUtils(userService);UserService proxyObject = (UserService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),UserServiceImpl.class.getInterfaces(), proxyUtils);proxyObject.add();}
}

JDK动态代理核心还是一个InvocationHandler,记住这个就行了。

转载于:https://www.cnblogs.com/borter/p/9590221.html

AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题相关推荐

  1. AOP面向切面编程在Android开发中的应用

    面向切面编程-Aspect Oriented Programming,简称AOP,通过预编译的方式和运行期间动态代理实现程序功能的统一维护的一种技术. AOP能够做什么呢? 性能检测 权限验证 释放资 ...

  2. AOP (面向切面编程)

    AOP (面向切面编程) 编辑 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AO ...

  3. AOP(面向切面编程)、Filter(过虑器)、Interceptor(拦截器)

    AOP(面向切面编程) 面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承.多态和封装.而封装就要求将功能分散到不同的对象中去,这在软 ...

  4. AOP就是面向切面编程,我们可以从几个层面来实现AOP。 ![](https://upload-im

    AOP就是面向切面编程,我们可以从几个层面来实现AOP. 在编译器修改源代码,在运行期字节码加载前修改字节码或字节码加载后动态创建代理类的字节码,以下是各种实现机制的比较. spring AOP是Sp ...

  5. Spring核心AOP(面向切面编程)

    AOP(面向切面编程) 原理 相关术语 系统日志增强 异常抛出增强 最终增强 环绕增强 使用注解实现AOP AspectJ 转载于:https://www.cnblogs.com/xhddbky/p/ ...

  6. Spring三大核心思想之AOP(面向切面编程)

    Spring三大核心思想之AOP(面向切面编程) 学习Spring三大核心思想之AOP之前建议先学习:

  7. 【SSM框架系列】Spring 的 AOP(面向切面编程)

    什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP 是 OOP ...

  8. Spring核心AOP(面向切面编程)总结

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/75208354冷血之心的博客) 目录 1.AOP概念: 2.AOP特 ...

  9. 简单理解AOP(面向切面编程)

    来源:http://www.cnblogs.com/jyh317/p/3834271.html AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式 ...

最新文章

  1. python下载opencv库_Window系统下Python如何安装OpenCV库
  2. 牛客网-斐波那契数列
  3. Perl文档操作选项
  4. 【OpenCV 例程200篇】59. 非线性滤波—双边滤波
  5. mysql连接代码_MySQL 表连接
  6. go redis 清空所有值_【大厂面试】面试官看了赞不绝口的Redis笔记二
  7. ROS学习笔记八:创建ROS msg和srv
  8. python周末看什么电影_电影院要开工了,用Python看一看最近有什么刚上映的电影...
  9. [Android Pro] 内容提供者ContentProvider的基本使用
  10. 如何在Spring容器中加载自定义的配置文件
  11. 一键下载百度文库/豆丁/道客巴巴文档,支持导出PDF,Word,txt 文件
  12. 电视盒子刷鸿蒙系统,家里的智能电视能装鸿蒙系统吗?鸿蒙系统有哪些优势?...
  13. 影片剪辑实例名的几点注意
  14. android 实现进度条的画面加载
  15. 时间日期插件引用使用方法
  16. 报Keystore was tampered with, or password was incorret的原因
  17. 微信诞生8年了,但还有8亿人不懂微信聊天礼仪
  18. cpu占用高 mongo_记一次 MongoDB 占用 CPU 过高问题的排查
  19. MapReduce之Map join操作
  20. linux之mmc子系统

热门文章

  1. 在1到100中找出所有和为100的数字组合
  2. T100客户端接口开发实例(T100对接销售易CRM)
  3. 一文搞懂 | ARM MMU
  4. vsCode运行python设置argparse参数
  5. Final Cut Pro X——fcpx视频剪辑软件中文版
  6. C++ 反序 swap32
  7. 华为v5服务器组硬盘卡,华为RH2288V5服务器RAID迁移(Avago SAS3408iMR RAID控制卡)
  8. 华硕 内存条 不同步_这颜值谁不爱呢?阿斯加特 洛极W3 RGB内存条 开箱评测
  9. 【echarts】数据可视化之桑葚图
  10. 关于WiderPerson数据说明(使用后笔记)