我们知道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. hdu4821 String

    您也可以在我的个人博客中阅读此文章:跳转 题意 一个字符串S 问其中有几个子串能满足以下条件:1.长度为m*l2.可以被分成m个l长的不同的子串问题就变成了如何快速的判断着m个子串是否存在相同的 思路 ...

  2. mysql主从复制的异步复制与同步复制

    异 步复制:MySQL本身支持单向的.异步的复制.异步复制意味着在把数据从一台机器拷贝到另一台机器时有一个延时 – 最重要的是这意味着当应用系统的事务提交已经确认时数据并不能在同一时刻拷贝/应用到从机 ...

  3. Python练习----购物车

    要求: 1.启动程序后,输入用户名密码后,如果是第一次登录,让用户输入工资,然后打印商品列表 2.允许用户根据商品编号购买商品 3.用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒 4.可随时 ...

  4. C# 使用HtmlAgilityPack抓取网页信息

    前几天看到一篇博文:C# 爬虫 抓取小说 博主使用的是正则表达式获取小说的名字.目录以及内容. 下面使用HtmlAgilityPack来改写原博主的代码 在使用HtmlAgilityPack之前,可以 ...

  5. 谈谈你对web标注和W3c的理解和认识

    web标准简单来说可以分为结构.表现和行为.其中结构主要是有HTML标签组成.表现即指css样式表,通过css可以是页面的结构标签更具美感.行为是指页面和用户具有一定的交互,同时页面结构或者表现发生变 ...

  6. ios 类的内部结构

    1. Class 和 Object 的定义 /// An opaque type that represents an Objective-C class. typedef struct objc_c ...

  7. POJ3468(线段树 区间修改 lazy-tag)

    我的线段树真的没救了......还是多练几道吧....... You have N integers, A1, A2, ... , AN. You need to deal with two kind ...

  8. Tickets

    Tickets Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Stat ...

  9. React + Node 单页应用「一」前端搭建

    项目地址 预览地址 原文地址 记录最近做的一个 demo,前端使用 React,用 React Router 实现前端路由,Koa 2 搭建 API Server, 最后通过 Nginx 做请求转发. ...

  10. 《剑指offer》面试题的Python实现

    <剑指Offer>是很多程序员面试前要看的书,但里面的算法都是基于C++实现的,最近用了三周左右时间,用Python完成了里面几乎所有的算法题,由于时间以及个人水平均有限,或许会有部分问题 ...