我们知道AOP指的就是设计模式中的代理模式。

一种是静态代理,高效,但是代码量偏大;

另一种就是动态代理,常见的有SDK下的动态代理,和CGLIB的动态代理,此外呢,还有注解式代理等等。

Spring框架下的AOP内容确实很多,也只能讲很多,没办法一一罗列,

本文例举的是Bean函数执行时候的一些代理。

AOP核心概念

我们自己写AOP会轻松很多,更加自由,而Spring对AOP进行了细致的划分,这种划分方式是被大部分企业所接受的,了解并使用Spring自身的AOP,可以降低集成其它框架的难度。

下面介绍一些专有名词。

1、横切关注点
对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
2、切面(aspect)
就如图所示,程序流程会按顺序执行,而切面就像一个平面,在这个流程中间插入,这种插入对原先代码是无破坏性的,不需要修改原先代码即可实现。
3、连接点(joinpoint)
被拦截到的点,它可以是程序执行过程中的任意一点,而AOP主要做的是方法上的拦截。
4、切入点(pointcut)
对连接点进行拦截的定义,切面与流程的交点。
5、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类。
6、目标对象
代理的目标对象
7、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
8、引入(introduction)
在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段

AOP的分类(增强分类)

此处的标题提到了增强,什么是增强?其实就是AOP了,至于为什么这么取名,只能问我们的前辈了,我见到就有这个名词了……

通常认为Spring在Bean的配置中有5种类型增强(根据英译,我认为应当是3种增强,2种拦截)。

代码上的直观感受就是五个接口了:

前置增强:org.springframework.aop.BeforeAdvice,其中BeforeAdvice是一个空接口,MethodBeforeAdvice是目前可用的前置增强,这个接口中实现前置方法。

后置增强:org.springframework.aop.AfterReturningAdvice,这个接口中要实现后置方法。

异常抛出增强:org.springframework.aop.ThrowsAdvice,代表抛出异常增强,此接口的函数在异常的时候执行。

环绕增强(方法拦截):org.aopalliance.intercept.MethodInterceptor,直译上看,它应该叫方法拦截,也就是说实现这个接口,可以不让我们的方法执行。

引介增强:org.springframework.aop.IntroductionInterceptor,IntroductionInterceptor的方法只有一个Class参数,并不十分方便使用,可以直接继承DelegatingIntroductionInterceptor类。它也是一种拦截方法,可以使用表示在目标类中添加一些新的方法和属性。

源码

环绕增强(拦截器)

这个和传统的JDK代理和CGLIB代理最类似,这里你可以获取到你需要调用的方法,你要是想放弃使用前置增强和后置增强,将它们的代码全部放在这里执行,这也是可以的。

具体的使用呢,就比如说:你要做一件很耗内存的操作,执行那个操作之前,你要判断内存容量,要是内存不足了,就放弃对方法的使用,这样的代码逻辑就可以放到这里。

/**
* 这是一个拦截器,在某些情况下,选择放弃对方法的使用,其实在这里编写前置代理和后置代理也可以,但是Spring既然提供了其他接口,参照接口实现更加规范
* @author ChenSS
* @2017年1月1日
*/
public class MyMethodInterceptor implements MethodInterceptor{ @Override
public Object invoke(MethodInvocation dao) throws Throwable {
System.out.println("MyMethodInterceptor执行");
// TODO 方法执行前要做的事情 //如果说,不执行下面这一行代码,则目标方法将不执行,其他的增强效果也全部失效
Object result= dao.proceed(); // TODO 方法执行后要做的事情
return result;
}
}

前置代理

/**
* 前置增强,也就是说这些代码会在你需要调用的那个方法之前执行
* @author ChenSS
* @2017年1月1日
*/
public class MyMethodBeforeAdvice implements MethodBeforeAdvice{ @Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName()+"方法执行之前");
}
}

后置增强

/**
* 后置增强,这些代码会在你需要调用的那个方法之后执行
* @author ChenSS
* @2017年1月1日
*/
public class MyAfterReturningAdvice implements AfterReturningAdvice{ @Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(method.getName()+"方法执行结束");
}
}

异常抛出增强

/**
* 这个接口实际是一个空的接口,但是方法体还是得参照规范写,具体捕捉什么异常要写清楚
* @author ChenSS
* @2017年1月1日
*/
public class MyThrowsAdvice implements ThrowsAdvice{
/**
* 笼统地使用了Exception,可以做具体的异常捕捉
*/
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
System.out.println(method.getName()+"出现异常");
}
}

引介增强

/**
* 这个呢,也是一种拦截方法,也可以拦截方法的执行,
* @author ChenSS
* @2017年1月1日
*/
public class MyIntroductionInterceptor extends DelegatingIntroductionInterceptor{
private static final long serialVersionUID = 2582891122340903718L; public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("引介增强启动拦截");
return super.invoke(mi);
}
}

测试函数

这里直接使用硬编码的方式进行测试,具体的Spring配置可以参考其它博主的文章。

目前大部分框架都封装得接近完美,加上注解的使用,实际编码过程中,使用的可能性约等于零;

但是如果自己写框架,需要的时候是真的有用,这篇文章我自己也回来看过很多次,今天做了一些修改。

                                        ---2017.12.19 22:03

/**
* 测试用接口
* @author ChenSS
* @2017年1月1日
*/
public interface BaseDao {
public long queryId() ;
public String queryName();
}
/**
* 测试用Dao
* @author ChenSS
* @2017年1月1日
*/
public class UserDao implements BaseDao{
public long queryId() {
System.out.println("queryId方法执行中");
System.out.println("故意制造一个算术异常");
return 2/0;
} public String queryName() {
System.out.println("queryName方法执行中");
return "xiaoming";
}
}

主函数

/**
* 测试函数
*
* @author ChenSS
* @2017年1月1日
*/
public class Test {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory();
// 把我们写的四种代理全部放进去
factory.addAdvice(new MyMethodInterceptor());
factory.addAdvice(new MyMethodBeforeAdvice());
factory.addAdvice(new MyAfterReturningAdvice());
factory.addAdvice(new MyThrowsAdvice()); // 引介增强比较特殊,需要提供接口
factory.addAdvice(new MyIntroductionInterceptor());
factory.setInterfaces(BaseDao.class.getInterfaces()); // 需要代理的那个类
factory.setTarget(new UserDao()); try {
UserDao dao = (UserDao) factory.getProxy();
System.out.println(dao.queryName());
System.out.println();
System.out.println(dao.queryId());
} catch (Exception e) {
// TODO: handle exception
}
}
}

测试结果如下:


发现研究框架花了太多时间了,原计划年前将Spring框架写清楚,但是发现内容真的好多啊,暂时也只能写到这了,之后我得回归安卓了,做一些安卓的研究,这些天有点荒废安卓了。

各位新年快乐哈,不过文章发表似乎已经1月2号了,O(∩_∩)O哈哈~

Spring框架——AOP代理的更多相关文章

  1. spring框架 AOP核心详解

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

  2. 跟着刚哥学习Spring框架--AOP(五)

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  3. spring框架aop用注解形式注入Aspect切面无效的问题解决

    由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...

  4. Spring框架_代理模式(静态代理,动态代理,cglib代理)

    共性问题: 1. 服务器启动报错,什么原因? * jar包缺少.jar包冲突 1) 先检查项目中是否缺少jar包引用 2) 服务器: 检查jar包有没有发布到服务器下:                 ...

  5. Spring框架-AOP详细学习[转载]

    参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...

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

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

  7. 10 Spring框架 AOP (三) Spring对AspectJ的整合

    上两节我们讲了Spring对AOP的实现,但是在我们的开发中我们不太使用Spring自身的对AOP的实现,而是使用AspectJ,AspectJ是一个面向切面的框架,它扩展了Java语言.Aspect ...

  8. Spring框架AOP学习总结(下)

    目录 1. AOP 的概述 2. Spring 基于AspectJ 进行 AOP 的开发入门(XML 的方式): 3.Spring 基于AspectJ 进行 AOP 的开发入门(注解的方式): 4.S ...

  9. 记一次Spring的aop代理Mybatis的DAO所遇到的问题

    由来 项目中需要实现某个订单的状态改变后然后推送给第三方的功能,由于更改状态的项目和推送的项目不是同一个项目,所以为了不改变原项目的代码,我们考虑用spring的aop来实现. 项目用的是spring ...

随机推荐

  1. WPF 圖表控件 MetroChart

    Torsten Mandelkow MetroChart包括以下: ColumnChart(ClusteredColumnChart,StackedColumnChart,StackedColumnC ...

  2. 搭建阿里云 centos mysql tomcat jdk

    [toc] 阿里云使用centos 登录 http://www.aliyun.com/ 点击登录 进入控制 https://home.console.aliyun.com/ 云服务器 运行中 把ip输 ...

  3. js 中 new fn与new fn()的区别

    在有些代码中,看见了let fn = new Fn()和let fn = new Fn,刚开始有些人或许和我一样感到些许疑惑,但潜意识的也会想到,这两者说不定就是一样的.没错!!在没有参数的情况下这两 ...

  4. (转)利用JConsole工具监控java程序内存和JVM

    转自:http://www.cnblogs.com/luihengk/p/5446279.html 一.找到java应用程序对应的进程PI 性能测试应用程序访问地址:http://192.168.29 ...

  5. (转)uml各类图

    原文:http://www.cnblogs.com/way-peng/archive/2012/06/11/2544932.html 一.UML是什么?UML有什么用? 二.UML的历史 三.UML的 ...

  6. 前端页面中如何在窗口缩放时让两个div始终在同一行显示

    直接贴代码吧 先总结一下吧  有两种方法 一    最外层设置一个大div  给这个大div固定的宽度和高度 给里面两个小div 设置浮动  设置宽高 <!DOCTYPE html> &l ...

  7. Jenkins项目部署使用教程-----02视图及项目添加

    注意:此以我公司为例,以svn上传代码 一.添加视图 1.点击右上角”+”号,新建新视图 勾选在该视图下显示的项目或者在该视图新建项目,点保存即可. 二.新建项目 1.点击左上角的新建,创建新项目. ...

  8. Travel

    Travel Time Limit: 10000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  9. 【Spring】渲染Web视图

    前言 前面学习了编写Web请求的控制器,创建简单的视图,本篇博文讲解控制器完成请求到结果渲染到用户的浏览器的过程. 渲染Web视图 理解视图解析 前面所编写的控制器方法都没有直接产生浏览器中渲染所需要 ...

  10. 磁盘管理 之 parted命令添加swap,文件系统

    第1章 磁盘管理 1.1 必须要了解的. 1.1.1 ps aux 命令中 RSS 与VSZ的含义 rss 进程占用的物理内存的大小 单位:kb : vsz 进程占用的虚拟的内存大小(物理内存+swa ...