最近在学习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. 关于新加坡IT薪酬

    很多朋友发邮件或留言问我关于新加坡IT薪酬的问题,由于前段时间比较忙,所以没有及时一一回复,在此表示抱歉. 新加坡IT薪酬范围大概如下(月薪,新加坡币对人民币为1:5): Junior Develop ...

  2. delegate、notification、KVO场景差别

    delegate: 编译器会给出没有实现代理方法的警告 一对一 使用weak而不是assign,或者vc消失时置为nil 可以传递参数,还可以接收返回值 notification: 编译期无法排错 一 ...

  3. 手写原生ajax

    关于手写原生ajax重要不重要,各位道友自己揣摩吧, 本着学习才能进步,分享大家共同受益,自己也在自己博客里写一下 function createXMLHTTPRequest() { //1.创建XM ...

  4. UITableView 一直显示滚动条(ScrollBar Indicators)、滚动条Width(宽度)、滚动条Color(颜色)

    在 IOS 中,对 UIScrollView 的滚动条(ScrollBar Indicators)的自定义设置接口,一直都是很少的.除了能自定义简单的样式(UIScrollViewIndicatorS ...

  5. C#设计模式系列:建造者模式(Builder)

    1.建造者模式简介 1.1>.定义 建造者模式(Builder)将复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 1.2>.使用频率 中低 1.3>.原型模式应用 ...

  6. 动态给div中新增html

    小颖最近接触的项目中用到了    innerHTML 所以小颖今天就自己做了个demo,当当当当代码请看下方: 页面效果:

  7. Vue.js学习笔记(6)tree

    分享一段用 <ul>和<li>标签实现tree的代码,可能写的不是很好,如果大家有更好的希望和小颖分享下.嘻嘻 啦啦啦,代码看这里喽: <div class=" ...

  8. 创建 router 连通 subnet- 每天5分钟玩转 OpenStack(100)

    上一节我们为 Neutron 虚拟路由器配置好了 L3 agent,今天将创建虚拟路由器“router_100_101”,打通 vlan100 和 vlan101. 打开操作菜单 Project -& ...

  9. 使用jQuery Draggable和Droppable实现拖拽功能

    上篇博客中已经介绍了web开发中基本拖放原理,现在给出需要完成的功能.最后运行的效果如下图所示: 主要功能需求说明: 1.左侧的元素结构最后会通过Ajax call服务器的数据来生成,能支持多级元素. ...

  10. 从零开始编写自己的C#框架(10)——项目实施计划与甘特图

    不知不觉本系列已经写了一个月,编码前的各项工作到此也终于结束了.回头看看这一个月走过来,白天上班晚上码字查资料,写写改改,挺不容易的.很多时候有些知识会用,知道是怎么回事,但并不等于能写出来.错别字. ...