【Spring】AOP(一) 基本概念

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

前言

     小编在学习一本书《spring 技术内幕》,书中讲解源码,以及源码的设计思路,通过AOP这章内容的学习,小编发现需要拿出来总结一番了。(百度网盘地址:https://pan.baidu.com/s/1mA1NCehfmB8deud8f3w2xQ   提取码:zzsd )

AOP概念   

1. Aspect-Oriented Programming,面向方面编程或面向切面编程。

2.维基百科中解释

   Aspect是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点(crosscutting concern),从关注点中分离出横切关注点是面向切面编程的核心概念。

3.模块化

c语言程序设计,体现了模块化,分而治之,一个大函数分解成多个子函数;

面向对象的设计方式,也是一种模块化方法,计算尽可能靠近数据,通过继承来重用和管理方法;在功能重复需要用在不同地方,继承方法无法很好解决这个问题,AOP可以将重复的代码抽取出来单独维护,在需要使用时统一调用。

AOP体系结构

   AOP联盟定义的AOP体系结构把与AOP相关的概念大致分为由高到低、由使用到实现三个层次。

一、语言和开发环境

这是最高层,分为基础、切面和配置

1.基础(base):待增强对象或目标对象

2.切面(aspect):包含对基础的增强应用

3.配置(configuration):可以看成是一种编织,通过配置完成切面对目标对象的编织实现。使用IOC容器来实现编织配置。

使用Java语言实现增强对象与切面增强

二、面向方面系统

   主要包括配置和编织实现两部分,对这些实现进行抽象的高级API封装,为最高层提供了有力的支持。

三、编织实现模块

  使用Java语言的特性,如Java 的Proxy代理类、拦截器等技术,实现AOP编织。

  具体实现方法:反射、程序预处理、拦截器框架、类装载器框架、元数据处理等。

Advice通知

一、基本概念

   Advice(通知)定义在连接点做什么,为切面增强提供织入接口。

  Spring AOP 的实现中, 使用了这个统一接口,为AOP的切面增强的织入功能做了更多的细化和扩展,比如添加了具体的通知类型,如BeforeAdvice、AfterAdvice、ThrowsAdvice等接口。

二、BeforeAdvice的实现

1.类层次结构

 在BeforeAdvice的继承关系中,定义了为待增强的目标方法设置的前置增强接口MethodBeforeAdvice,使用这个前置接口需要实现一个回调函数:

void before(Method method,Object[] args,Object target)throws Throwable;

 作为回调函数,会在Advice中被配置到目标方法后,调用目标方法时被回调。

2.具体的调用参数

Method对象,这个参数是目标方法的反射对象;

Object[]对象数组,包含目标方法的输入参数;

Object target 

3.BeforeAdvice的具体使用

(1)CountingBeforeAdvice是接口MethodBeforeAdvice的具体实现,统计被调用方法的次数。

 作为切面的增强,它会根据调用方法的方法名进行统计,把统计结果根据方法名和调用次数作为键值放入一个map中。

public class CountingBeforeAdvice extends MethodCounter implements MethodBeforeAdvice{
 public void before(Method m,Object[] args,Object target)throws Throwable{
    count(m);
   }   
}

 (2)MethodCounter作为基类,实现了count(method m)方法

   在统计过程中,首先通过目标方法的反射对象得到方法名,然后进行累加,把统计结果放到维护的哈希表中,如果需要统计数据,就到哈希表中根据key值去取。

public class MethodCounter implements Sirializable{
  // 这个hashMap用来存储方法名和调用次数的键值对
  private HashMap<String,Integer> map=new HashMap<String,Integer>();
  // 调用的次数,不管什么方法名
  private int allCount;

  protected void count(Method m){
    // CountingBeforeAdvice的入口
    count(m.getName()); 
  }
  
  // 根据方法名统计调用次数
  protected void count(String methodName){
   Integer i=map.get(methodName);
   i=(i!=null) ? new Integer(i.intValue()+1):new Integer(1);
   map.put(methodName,i);
   ++allCount;
  }

  // 根据方法名取得调用次数
  public int getCalls(String methodName){
   Integer i= map.get(methodName);
   return (i!=null ? i.intValue:0);
 
  }

  // 取得所有方法的调用次数
  public int getCalls(){
   return allCount;
  }

  public boolean equals(Object other){
   return(other!=null && other.getClass()==this.getClass());
  }

  public int hashCode(){
   return getClass.hashCode;
  }

}

小结

  补充两个概念:

  1.回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

 2.反射:

反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,但是“反”指的是通过对象找到类。

用于 reflection 的类,如 Method,可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中,用 java.lang.Class 类来描述类和接口等。

下面就是获得一个 Class 对象的三个方法:

Class c = Class.forName("java.lang.String");
Class c = int.class;
Class c = Integer.TYPE;

推荐博客:https://www.cnblogs.com/cs-lcy/p/7397955.html

                                                                           感谢您的访问!

猜你喜欢

转载自blog.csdn.net/m18633778874/article/details/92191739