最近在学习AOP,之前一直很不明白,什么是AOP?为什么要使用AOP,它有什么作用?学完之后有一点小小的感触和自己的理解,所以在这里呢就跟大家一起分享一下

AOP(Aspect-Oriented Programming)其实是OOP(Object-Oriented Programing) 思想的补充和完善。我们知道,OOP引进"抽象"、"封装"、"继承"、"多态"等概念,对万事万物进行抽象和封装,来建立一种对象的层次结构,它强调了

一种完整事物的自上而下的关系。但是具体细粒度到每个事物内部的情况,OOP就显得无能为力了。比如日志功能。日志代码往往水平地散布在所有对象层次当
中,却与它所散布到的对象的核心功能毫无关系。对于其他很多类似功能,如事务管理、权限控制等也是如此。这导致了大量代码的重复,而不利于各个模块的重
用。   而AOP技
术则恰恰相反,它利用一种称为"横切"的技术,能够剖解开封装的对象内部,并将那些影响了多个类并且与具体业务无关的公共行为 封装成一个独立的模块(称
为切面)。更重要的是,它又能以巧夺天功的妙手将这些剖开的切面复原,不留痕迹的融入核心业务逻辑中。这样,对于日后横切功能的编辑和重用都能够带来极大
的方便。    AOP技术的具体实现,无非也就是通过动态代理技术或者是在程序编译期间进行静态的"织入"方式。下面是这方面技术的几个基本术语:

1、join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。

2、point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。

3、advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。

4、aspect(切面):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。

说了这么多,可能我们还是对AOP有点不知所措,不知道是干什么的,那么我们就以一个例子作为讲解,来理解这个抽象的概念

我们有一个简易的计算器,进行加减乘除的操作,有一个需求,1.需要在进行算法之前和之后进行输出一句话

那么对于以上操作我们可能最容易想到的就是用一个实现类实现这个接口。然后在接口调用方法前后输出一句话

这样确实能实现这个需求,但是可能有的同学就想到了,是不是重复代码了呢?如果我有上千个方法呢?是不是还得在每个方法里增加几行代码?我们能不能在不改变原来方法的结构上

也能实现相同的需求呢?这个时候AOP就能帮我们实现了。下面我们详细的讲解下如何使用注解的方式来实现AOP

还是同样的接口和实现类,只是这时候实现类中没有了输出语句,如图

上图就是最原始的方法了,也就是说我们在这个方法里面只需要关注我们方法执行的内容,并不需要关注一些方法之外的东西,比如说记录日志,方法前输出语句等等。。

那么,既然这个方法什么都不关注的话,那我们的输出语句又在哪儿写呢?这个时候我们就定义一个专门的类,用它来作为切面,代码如下所示

package advice;

import java.util.Arrays;
import java.util.List; import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; @Aspect //声明注解
public class CalculationAnnotation { /**
* 定义前置通知
* execution(* biz.UserBiz.*(..)) 表示 所有修饰符的所有返回值类型 biz.UserBiz 包下的所有方法
* 在方法执行之前执行
* */
@Before("execution(* biz.CalculationImpl.*(..))")
public void before(JoinPoint join){
//获取方法名
String mathName=join.getSignature().getName();
//获取参数列表
List<Object> args = Arrays.asList(join.getArgs()); System.out.println("前置通知---->before 方法名是:"+mathName+"\t参数列表是:"+args);
} /**
* 后置通知
* 在方法返回后执行,无论是否发生异常
* 不能访问到返回值
*
* */
@After("execution(* biz.CalculationImpl.*(..))")
public void after(){
System.out.println("后置通知---->after....");
}
}

@Aspect ----->表示声明这个类是一个切面,

这样呢,咱们这个切面就声明完毕了,那么,我们可以想到,这个时候我们只是声明了一个切面而已,并没有在那个地方用到这个切面对不对?也就是说我们配置的切面还跟我们程序还没有任何的关联关系

这样的话呢,就引出了我们的配置文件了也就是我们Spring的配置文件applicationContext.xml,配置如下

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
"> <!-- 配置Bean -->
<bean id ="CalculationImpl" class="biz.CalculationImpl"></bean> <!-- 将切面类交与Spring容器管理 -->
<bean class="advice.CalculationAnnotation"></bean> <!-- 使用注解自动生成代理对象 -->
<aop:aspectj-autoproxy/> </beans>

这个时候我们可以看看配置文件里到底写了什么,写这些是干啥的,有什么用。

这个大家肯定都懂是吧,这没话说,也就是将CalculationImpl类交给Spring容器来管理,如果有不懂的童鞋可以看看我的另一篇关于Spring  IOC 的文章

那么这行代码呢?这行代码的意思就是将我们的CalculationAnnotation类交给Spring容器管理,因为我们在CalculationAnnotation类中不是声明了一个@Aspect切面注解吗对不对

当Spring容器初始化的时候它会找有没有这个节点,如果有的话呢,容器就会根据你的Bean配置,找看那个类中配置了@Aspect切面注解

如果找到了的话那么就根据你的注解来执行相应的代码,什么意思呢?比如说如图所示

好,那么我们就来看看执行之后结果会是怎样的呢?

这样我们是不是就完成了之前的需求呢?在执行代码前输出一行语句,如果我们想要做到日志的记录的话,是不是只需要把输出语句修改为记录日志的代码就可以了呢。而且我还没有影响任何的功能性代码

也就是对源代码并没有做任何的修改,那么既然有前置增强的话肯定也有后置增强和其他增强操作下面我就讲讲后置增强,

其实对于其他的增强类型的话呢,既然知道前置增强是怎么一回事了,那么其他四种就轻而易举了

后置增强,其实我们只需要在切面类也就是我们写前置增强的类中直接添加后置 增强代码即可,如图

只是将注解标签给进行了一道修改,其他的任何操作我们都不需要在进行修改,示例结果如图所示

这样是不是就完成了在方法前后执行与方法无关的代码呢?可能有些童鞋有疑问,为什么输出语句是在最后输出的,不应该是夹在中间吗?但是我们看测试代码,我是执行了add方法,接收了一个返回值,然后在方法的外面输出的我接收的返回值变量,那么这样的话,可不就是我们看到的结果嘛。

由于时间的关系呢,我今天就先给大家分享下前置增强和后置增强。至于返回,异常和环绕的话呢,我就下次在跟大家分享吧!希望大家能够学到点东西吧!

详解Spring框架AOP(面向切面编程)的更多相关文章

  1. Spring详解篇之 AOP面向切面编程

    一.概述 Aop(aspect oriented programming面向切面编程),是spring框架的另一个特征.AOP包括切面.连接点.通知(advice).切入点(pointCut) . 1 ...

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

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

  3. Spring框架——AOP面向切面编程

    简介 AOP练习 使用动态代理解决问题 Spring AOP 用AspectJ注解声明切面 前置后置通知 利用方法签名编写AspectJ切入点表达式 指定切面的优先级 基于XML的配置声明切面 Spr ...

  4. Spring 08: AOP面向切面编程 + 手写AOP框架

    核心解读 AOP:Aspect Oriented Programming,面向切面编程 核心1:将公共的,通用的,重复的代码单独开发,在需要时反织回去 核心2:面向接口编程,即设置接口类型的变量,传入 ...

  5. Spring:AOP面向切面编程

    AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果. AOP是软件开发思想阶段性的产物,我们比较熟悉面向过程O ...

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

    .AOP 什么? AOP(Aspect Oriented Programming),通常称为面向切面编程.它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的 ...

  7. 03-spring框架—— AOP 面向切面编程

    3.1 动态代理 动态代理是指,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由 JVM 根据反射等机制动态生成的.代理对象与目标 ...

  8. spring:AOP面向切面编程02

    参考: https://blog.csdn.net/jeffleo/article/details/54136904 一.AOP的核心概念AOP(Aspect Oriented Programming ...

  9. Spring的AOP面向切面编程

    什么是AOP? 1.AOP概念介绍 所谓AOP,即Aspect orientied program,就是面向方面(切面)的编程. 功能: 让关注点代码与业务代码分离! 关注点: 重复代码就叫做关注点: ...

随机推荐

  1. Expert 诊断优化系列------------------语句调优三板斧

    前面三篇通过CPU.内存.磁盘三巨头,讲述了如何透过现在看本质,怎样定位服务器三巨头反映出的问题.为了方便阅读给出链接: SQL SERVER全面优化-------Expert for SQL Ser ...

  2. 每周一书-《鸟哥的Linux私房菜基础学习篇(第四版)》台湾原版,你想要吗?

     首先说明,本周活动有效时间为2016年10月19日到2016年10月31日.   目在介绍这本书之前,首先要感谢QQ号为:1084830483(路在远方),来自哈尔滨工程大学的同学赠送给玄魂工作室的 ...

  3. AngularJS基础入门初探

    一.AngularJS简介 1.1 什么是AngularJS (1)一款非常优秀的前端JS框架,可以方便实现MVC/MVVM模式 (2)由Misko Hevery 等人创建,2009年被Google所 ...

  4. Hadoop学习笔记—21.Hadoop2的改进内容简介

    Hadoop2相比较于Hadoop1.x来说,HDFS的架构与MapReduce的都有较大的变化,且速度上和可用性上都有了很大的提高,Hadoop2中有两个重要的变更: (1)HDFS的NameNod ...

  5. ASP.Net请求处理机制初步探索之旅 - Part 2 核心

    开篇:上一篇我们了解了一个请求从客户端发出到服务端接收并转到ASP.Net处理入口的过程,这篇我们开始探索ASP.Net的核心处理部分,借助强大的反编译工具,我们会看到几个熟悉又陌生的名词(类):Ht ...

  6. ARM的常数表达式

    ARM的常数表达式   如果说Intel指令中的立即数,相信大家都很熟悉.类似的,Arm指令中的“立即数”就是常数表达式.之所以称为常数表达式,而不称为立即数是有原因的. Intel指令属于CISC指 ...

  7. 小型文件数据库 (a file database for small apps) SharpFileDB

    小型文件数据库 (a file database for small apps) SharpFileDB For english version of this article, please cli ...

  8. [备忘]检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败解决方法

    检索 COM 类工厂中 CLSID 为 {91493441-5A91-11CF-8700-00AA0060263B} 的组件时失败,原因是出现以下错误: 80070005 在CSDN上总是有网友问这个 ...

  9. 缓存篇(Cache)~大话开篇

    回到占占推荐博客索引 闲话杂淡 想写这篇文章很久了,但总是感觉内功还不太够,总觉得,要写这种编程领域里的心法(内功)的文章,需要有足够的实践,需要对具体领域非常了解,才能写出来.如今,感觉自己有写这种 ...

  10. highchart导出图片

    http://www.cnblogs.com/jasondan/p/3504120.html 项目中需求导出报表为图片存到Excel中去,或供其它页面调用. 开始存到截屏,但由于用户电脑分辨率不一样, ...