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代理,前者基于接口,后者基于子类

  如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  二 Spring AOP

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

  三 基于注解的AOP配置方式

  1.启用@AsjectJ支持

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

  

  2.通知类型介绍

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

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

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

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

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

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

  3.例子:

  spring框架 AOP核心详解

  (1)Operator.java -- 切面类

  @Componentbr/@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

  

  

  (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通知的运行,不要同时使用!同时使用也没啥意义。

  如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  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的名称

  后言: spring 的环绕通知和前置通知,后置通知有着很大的区别,主要有两个重要的区别:

  1) 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知 是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的。

  2) 环绕通知可以控制返回对象,即你可以返回一个与目标对象完全不同的返回值,虽然这很危险,但是你却可以办到。而后置方法是无法办到的,因为他是在目标方法返回值后调用

  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 {

  @Resource

  private LogService logService;

  public Object record(ProceedingJoinPoint pjp){

  Log log = new Log();

  try {

  log.setOperator(admin);

  String mname = pjp.getSignature().getName();

  log.setOperName(mname);

  //方法参数,本例中是User user

  Object[] args = pjp.getArgs();

  log.setOperParams(Arrays.toString(args));

  //执行目标方法,返回的是目标方法的返回值,本例中 void

  Object 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

  

  

  

  

  

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

  如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。

  有关更详细的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://juejin.im/post/5c8b6a626fb9a049e6612377

spring框架 AOP核心详解相关推荐

  1. Spring框架面试题详解

    1. 什么是spring? Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标是简化Jav ...

  2. 【Spring框架】全集详解

    文章目录 ClassPathXmlApplicationContext工作原理 01.IOC:控制反转 02.什么是bean 03.DI注入以及c.p命名空间 ```p命名空间.c命名空间``` `` ...

  3. Spring之AOP原理详解

    概念 AOP 实现原理 AOP 动态代理的实现原理 实现AOP 链接上一篇:spring框架组件分析 概念 AOP spring用代理类包裹切面,把他们织入到Spring管理的bean中.也就是说代理 ...

  4. Spring框架@PostConstruct注解详解

    文章目录 前言 业务背景 通过依赖查找实现 `@PostConstruct`注解实现 @PostConstruct注解原理 `@PostConstruct`注解 `@PostConstruct`注解源 ...

  5. java spring框架 注解_详解Java的Spring框架中的注解的用法

    1. 使用Spring注解来注入属性 1.1. 使用注解以前我们是怎样注入属性的类的实现: class UserManagerImpl implements UserManager { private ...

  6. Spring面向切面编程(AOP)详解

    Spring面向切面编程(AOP)详解 面向切面编程(AOP)是Spring框架的另外一个重要的核心内容. 而在讲AOP之前,先来了解一下动态代理这个概念,因为AOP基于动态代理. 动态代理概念:在程 ...

  7. Spring 框架(Spring Framework)使用详解

    概述 Spring 体系概述 Spring 是于2003年兴起的一个 full-stack 轻量级的 Java 开源框架,由 Rod Johnson 创建,使用 Spring 可以更快.更轻松.更安全 ...

  8. Spring包含JAR的详解

    一.Spring 常用包的说明 spring.jar :  包含有完整发布模块的单个jar 包.但是不包括mock.jar, aspects.jar, spring-portlet.jar, and ...

  9. SpringBoot2.1.5(16)--- Spring Boot的日志详解

    SpringBoot2.1.5(16)--- Spring Boot的日志详解 市面上有许多的日志框架,比如 JUL( java.util.logging), JCL( Apache Commons ...

最新文章

  1. R语言中的聚类的使用
  2. WinForm中Partial部分类的使用
  3. 牛客网 对称平方数【回文数的判断 两个vector是否相等】
  4. 如何在Android Wear上节省电池寿命
  5. Python核心教程(第二版)读书笔记(三)
  6. 猜数字游戏(Java)
  7. xshell修改编辑文件并保存
  8. 求给定数组中两数和为给定值的数量
  9. zk临时节点失效时间_dubbo学习(六)服务发布dubbo服务在zk的创建、订阅
  10. 新浪php工程师面试题
  11. 《心灵捕手》经典台词
  12. mysql数据库储存过程
  13. 医疗在线质控系统 资料收集
  14. 深入浅出的马尔科夫入门文章
  15. 杨振宁与清华计算机系,我们都误会杨振宁了!看到清华给出的工资,才明白他有多伟大...
  16. 日历当前月 日期对应
  17. 获取现在的Unix时间戳(Unix timestamp)的方法-在线时间戳转换器
  18. 如何在日内趋势中交易?
  19. 扔物线Kotlin讲解学习(一)----Kotlin的权限修饰符详解
  20. 老杨说运维 | 企业数字化转型中,统一监控的必要性

热门文章

  1. c++ builder xe2 (Embarcadero rad studio) 远程调试 同样适用于 delphi 远程调试 教程
  2. 如何在ashx页面获取Session值
  3. 主机名修改 Oracle监听器,oracle agent不能启动的解决方案
  4. pycharm安装包时各种报错,且pip无法安装
  5. Visual Studio 2019 安装教程 附免费安装包资源
  6. Java实现八皇后问题的解法(一维数组版本)
  7. Matlab | matpower5.0:最优潮流执行步骤
  8. 计算机视觉与深度学习 | K-means聚类算法在计算机视觉中的应用之图像分割
  9. Windows消息:WM_USER与WM_APP的区别
  10. eclipse java 运行快捷键_java – 可以使用Eclipse中的键盘快捷方式启动/停止Tomcat吗?...