一、 引言

AOP(Aspect-Oriented Programming,面向切面的编程),是一种新型的编程范式,主张关注软件流程中的一个切面,将相同功能的代码整合打包在一起,减少系统的耦合性,增强其扩展性。

传统的软件设计,往往採取事件驱动模型带来相似的效果,通过在可能的事件切入点插入事件回调函数,将相应位置插入外置代码。

函数式编程,也有相似的解决方式,通过函数传递,将相应位置的扩展上新的功能。

Java作为一门严谨的传统式开发语言。以安全性和可靠性为第一标准。语言并没有过多的新特性支持,Java8仅支持到lambda表达式,为了使Java具有更强大的编程模型,Spring等框架使用gclib库实现了面向切面的编程模型。

二、 CGLIB 和 ASM

CGLIB 是一个强大的,高性能,高质量的Code生成类库。被广泛的用作动态代理技术。CGLIB 包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类,新的字节码能够被Java虚拟机直接载入运行。

事实上动态代理并非CGLIB的专利。早在JDK1.3版起,就引入了动态代理库。Spring AOP 编程时就能够进行选择,使用JDK提供的动态代理库。或者是引入CGLIB库。

以下举一个实例,来说明一些怎样使用CGLIB库,将我们本来应该正常运行的函数调用,进行截断操作。

package com.abs.testcglib;

public class Service {
String name; public Service(String name) {
this.name = name;
} public void sayHello() {
System.out.println("Hello "+name);
}
}

首先,我们创建一个服务类,当中有一个sayHello() 方法。我们希望将这种方法截断,以加入其余组件的一些处理功能,比如持久化组件希望在此加入一条记录一类的功能。

package com.abs.testcglib;

public class Main {
public static void main(String[] args) {
Service s = new Service("Sxf");
s.sayHello();
}
}

在Main函数中调用一下,能够看的Hello Sxf 的输出。

但我们怎么截断呢?首先就要创建一个代理类,所谓代理,就是你让这个代理类,代你调用这个类的函数。

创建一个代理类:

package com.abs.testcglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class CglibProxy implements MethodInterceptor { @Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("方法名:"+method.getName());
Service a = (Service) o;
a.name = "Wah";
System.out.println("哈哈,我要改名");
Object result = methodProxy.invokeSuper(o, args);
return result;
}
}

这个代理类的功能,就是将传统的Java直接的函数调用,包上一次外壳,由于Java本身的函数调用是系统完毕的。非常难由你大段他,但代理类不同,你能够明白的看的调用了哪个函数。而且能够依据这点,轻松的在函数调用前后。插入你希望插入的代码。

public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy)

这个函数大概是整个代理调用中最关键的一个函数了。o这个參数表示了该函数所在的对象,args是调用的參数。Method则是反射到的方法。最后一个则是代理的实例。

我们对函数的打断功能。则都在这个函数里实现。

当然,由于是通过代理实现,对象的构建也有所不同,所以我们自己写一个static函数作为构造函数使用。

package com.abs.testcglib;

import net.sf.cglib.proxy.Enhancer;

public class Service {
String name; public Service(String name) {
this.name = name;
} public void sayHello() {
System.out.println("Hello "+name);
} public static Service getProxyInstance(CglibProxy myProxy, String name) {
Enhancer en = new Enhancer();
// 设置父类和回调
en.setSuperclass(Service.class);
en.setCallback(myProxy);
// 调用其构造函数,须要传入相应的Class列表和參数Object列表
return (Service) en.create(new Class[] {String.class}, new Object[] {name});
}
}

而Main函数中也应该这样使用该对象:

package com.abs.testcglib;

public class Main {
public static void main(String[] args) {
Service s = new Service("Sxf");
s.sayHello(); Service s2 = Service.getProxyInstance(new CglibProxy(), "Sxf");
s2.sayHello();
}
}

我们发现,两种方式创建出的对象,使用上差点儿一样,唯一不同的就是构造函数时,我们进行了部分改动,其余部分,不影响我们的对象正常传递。存储等功能。

终于效果:

三、 Spring AOP 的实现

事实上看来刚才CGLIB的实现。再看著名的Spring框架。就会发现两者的实现方式差点儿全然一样,仅仅只是Spring框架多添加了一些概念和功能。

以下我们写一个Target 类。这是一个被代理的目标对象,当中有一个execute()方法。如今使用 AOPexecute()方法做日志输出。在运行execute()方法前。做日志输出。

public class Target {
public void execute(String name){
System.out.println("executeMethod is here" + name);
}
}

通知能够拦截目标对象的 execute()方法,并运行日志输出。创建通知的代码例如以下:

public class LoggerExecute implements MethodInterceptor {
public Object invoke(MethodInvocation arg0) throws Throwable {
before();
arg0.proceed();
return null;
}
private void before() {
System.out.println("executeMethod is exe!");
}
}

创建代理的方法也差点儿一样:

public static void main(String[] args) {
//创建目标对象
Target target = new Target();
//创建代理
ProxyFactory di=new ProxyFactory();
di.addAdvice(new BeforeExecute());
di.setTarget(target);
Target proxy=(Target)di.getProxy();
//代理运行execute()方法
proxy.execute(" ni hao");
}

当然Spring的切入点和其配置文件关联十分紧密。用Spring框架能够将系统的很多其它固定參数丢到配置文件里去,或者直接使用注解也能够。

Java的面向AOP编程的更多相关文章

  1. Java笔记——面向切面编程(AOP模式)

    原文:http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming  面向切面 ...

  2. JAVA中-面向网络编程---单层交互

    面向网络编程---单层交互: 客户端说明: /* * 实现TCP客户端,链接到服务器 * 和服务器实现数据交互 * 实现TCP客户端的类 java.net.Scoket * 构造方法: * Socke ...

  3. JAVA Spring 面向切面编程 基本案例(AOP)

    < 1 > 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...

  4. JavaEE开发之Spring中的依赖注入与AOP编程

    上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...

  5. Java实战之03Spring-03Spring的核心之AOP(Aspect Oriented Programming 面向切面编程)

    三.Spring的核心之AOP(Aspect Oriented Programming 面向切面编程) 1.AOP概念及原理 1.1.什么是AOP OOP:Object Oriented Progra ...

  6. Java 面向切面编程(Aspect Oriented Programming,AOP)

    本文内容 实例 引入 原始方法 装饰者模式 JDK 动态代理和 cglib 代理 直接使用 AOP 框架--AspectWerkz 最近跳槽了,新公司使用了 AOP 相关的技术,于是查点资料,复习一下 ...

  7. java aop面向切面编程

    最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...

  8. 【Java】Spring之面向方面编程(AOP)(五)

    面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP).OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面.方面实现了跨越多种类型和对象的关注点(例如事务管理)的 ...

  9. 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring AOP(面向切面编程)

    面向切面编程(AOP)和面向对象编程(OOP)类似,也是一种编程模式.Spring AOP 是基于 AOP 编程模式的一个框架,它的使用有效减少了系统间的重复代码,达到了模块间的松耦合目的. AOP ...

随机推荐

  1. Linux平台下使用AdventNet ManageEngine OpUtils监控网络

    AdventNet ManageEngine OpUtils 是一套系统和网络监视工具,它有Linux/Windows系统平台的免费版和企业版,该软件是一款用于监视诸如路由器,交换机,服务器或者桌面这 ...

  2. 用C#生成随机中文汉字验证码的基本原理

    前几天去申请免费QQ号码,突然发现申请表单中的验证码内容换成了中文,这叫真叫我大跌眼镜感到好笑,Moper上的猫儿们都大骂腾讯采用中文验证码.^_^  我不得不佩服腾讯为了防止目前网络上横行的QQ号码 ...

  3. 微信小程序弹框提示绑定手环实例

    今天想聊一聊小程序里面存在的一些逻辑问题,拿手上的这个小程序来说,(这个小程序是开发出来玩的,每个人手上有一个手环,带着手环时候的心率,运动步数,血压数据都会展现在这个小程序里面,一目了然)用户第一次 ...

  4. 洛谷 P2655 2038年问题

    P2655 2038年问题 题目描述 网络时代,机会与危机共存.“千年虫”解决之后,会不会有新的“虫”出现?回答是肯定的,“2038年”就是一个新的关卡. 也许大家都已经知道计算机的2000年问题是什 ...

  5. Android中的帧动画与补间动画的使用

    前言 在日常开发中,我们有时候须要一些好看的动画效果,这时能够充分利用Android提供的这几种动画来实现. Android提供了3种类型的动画: 补间动画:补间动画能够应用于View,让你能够定义一 ...

  6. C# 依据KeyEventArgs与组合键字符串相互转换

    /// 快捷键相关的类 /// </summary> public static class HotKeyInfo { /// <summary> /// 依据KeyEvent ...

  7. 学习笔记(一):offset

    很多初学者对于JavaScript中的offset.scroll.client一直弄不明白,虽然网上到处都可以看一张图(图1),但这张图太多太杂,并且由于浏览器差异性,图示也不完全正确. 图一 不知道 ...

  8. golang sort

    package main import ( "fmt" "strings" "sort" ) type Animals []string f ...

  9. Redis的高级应用-安全性和主从复制

    Redis的服务器命令和键值命令(String,Hash,List,Set,Zset)相对简单,只需查看文档即可. 文档地址: http://www.runoob.com/redis/redis-tu ...

  10. 使用Struts2和jQuery EasyUI实现简单CRUD系统(七)——数据分页处理

    上篇完毕多选删除的功能之后,接下来就是做分页功能了.曾经的分页是一个麻烦的问题.并且数据量巨大的时候,直接把这些元素取出来显然速度较慢,所以取一定区间的数据还是高效的. watermark/2/tex ...