博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring理论基础-面向切面编程
阅读量:7034 次
发布时间:2019-06-28

本文共 2370 字,大约阅读时间需要 7 分钟。

AOPAspect-Oriented Programming的缩写,中文翻译是面向切面编程。作为Spring的特征之一,是要好好学习的。

首先面向切面编程这个名称很容易让人想起面向对象编程(OOP)来。我们知道面向对象编程是从上往下的把系统拆分成若干个类,如Web项目中常见的ControllerServiceDao等分层。但是面向对象编程对于从左到右的水平抽象十分无力,类似于日志、权限等系统级功能的代码会重复的出现在任何地方。简单的说,面向切面编程是对面向对象编程的一种补充,它可以把系统里一些分散的重复代码集中在一起,抽象成一个切面。先来举一个例子:

有一个内部使用的管理系统,Controller中的每个接口在调用时都要记录下当前用户名称、当前时间等参数。

很明显这个需求的实现代码在每个接口中都是重复的。即使提取成公共类的公共方法,在每个接口里也都有一句该公共方法的调用,导致类之间的耦合。

我们希望把原来接口中的记录代码去除掉,使这些接口只关注自己的业务逻辑。然后使用预编译或运行期动态代理等方式实现在不修改接口代码的情况下,为接口添加记录功能。这种动态地将代码织入到类的指定方法、指定位置上的编程思想就是面向切面编程。

概念

面向切面编程具体的一些概念。

《EXPERT ONE ON ONE J2EE DEVELOPMENT WITHOUT EJB》第8章、《Spring实战》第4章:

  • 增强(advice,另译为通知,但《Spring3.x企业应用开发实战》作者不赞成):在特定连接点执行的动作。例子中的实现代码就是增强。

  • 切点(pointcut):一组连接点的总称,用于指定某个增强应该在何时被调用。例子中的指定哪些接口和指定位置就是切点。

  • 连接点(join point):在应用执行过程中能够插入切面的一个点。例子中具体的一个接口和指定位置的结合就是连接点。

  • 切面(aspect):通知(即增强)和切点的结合。

AOPSpring中主要是通过动态代理实现的,具体实现也分为两种:JDK动态代理CGLIB动态代理。其中JDK动态代理是基于接口代理,CGLIB动态代理是基于继承代理。

JDK动态代理

作为Java自带的一种动态代理技术,JDK动态代理的优势是使用反射技术来生成代理类,在生成效率上比较高。缺点是只能基于接口来动态代理,如果目标类没有实现任何接口是不能使用JDK动态代理的。

来看一个用JDK动态代理的例子。

public class DynamicProxy implements InvocationHandler {    /**     * 被代理类     */    private Object target;    public DynamicProxy(Object target) {        this.target = target;    }    public static Object bind(Object target) {        InvocationHandler invocationHandler = new DynamicProxy(target);        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), invocationHandler);    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println(method.getName() + " 方法执行前");        //执行被代理类方法        Object ret = method.invoke(target, args);        System.out.println(method.getName() + " 方法执行后");        return ret;    }    public static void main(String[] args) {        Dao dao = new OrderDao();        dao.doSomeThing();        Dao daoProxy = (Dao) DynamicProxy.bind(dao);        daoProxy.doSomeThing();    }}复制代码
public class OrderDao implements Dao {    @Override    public void doSomeThing() {        System.out.println("test");    }}复制代码
public interface Dao {    void doSomeThing();}复制代码
输出:testdoSomeThing 方法执行前testdoSomeThing 方法执行后Process finished with exit code 0复制代码

后记

这次只是梳理下概念,把自己理解的AOP概念写下来。也参考了很多文章,大体都是一致的细节上有些不同,把自己理解的写出来给大家看下就知道有没有错了。顺便整理一下,免得以后别人问起自己支支吾吾的不知道从哪说起。并没有去了解Spring中具体的AOP实现,有兴趣的同学可以自行深入了解下。

参考资料

转载地址:http://xeyal.baihongyu.com/

你可能感兴趣的文章
boost mutex以及scoped_lock应用
查看>>
小鸡吃米
查看>>
FFmpeg AVFMT_NOFILE宏定义剖析
查看>>
Windows Server 2008 R2活动目录回收站
查看>>
能吃遍全世界的方便面,你也是人生赢家
查看>>
为什么使用LR11录制完,发现脚本每个页面都被录制了两遍?
查看>>
Fedora 删除旧内核
查看>>
浏览器静态资源的版本控制新思路.强制更新指定资源缓存.的探讨
查看>>
NSCalendar
查看>>
Ios 入门 ----WebView 控件
查看>>
scala编译错误
查看>>
VMware Horizon 6 介绍
查看>>
ansible的使用
查看>>
2012年2月10日
查看>>
Linux下Web服务器应用之网站安全-https
查看>>
关于循环嵌套循环
查看>>
Scala中常见的容器 Option(选项)
查看>>
算法-蛇型矩阵
查看>>
路由交换IOS的备份与还原
查看>>
05.swift ?可选类型
查看>>