Java的面向AOP编程
一、 引言
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()
方法。如今使用 AOP 对 execute()
方法做日志输出。在运行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编程的更多相关文章
- Java笔记——面向切面编程(AOP模式)
原文:http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html Aspect Oriented Programming 面向切面 ...
- JAVA中-面向网络编程---单层交互
面向网络编程---单层交互: 客户端说明: /* * 实现TCP客户端,链接到服务器 * 和服务器实现数据交互 * 实现TCP客户端的类 java.net.Scoket * 构造方法: * Socke ...
- JAVA Spring 面向切面编程 基本案例(AOP)
< 1 > 配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=&q ...
- JavaEE开发之Spring中的依赖注入与AOP编程
上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...
- Java实战之03Spring-03Spring的核心之AOP(Aspect Oriented Programming 面向切面编程)
三.Spring的核心之AOP(Aspect Oriented Programming 面向切面编程) 1.AOP概念及原理 1.1.什么是AOP OOP:Object Oriented Progra ...
- Java 面向切面编程(Aspect Oriented Programming,AOP)
本文内容 实例 引入 原始方法 装饰者模式 JDK 动态代理和 cglib 代理 直接使用 AOP 框架--AspectWerkz 最近跳槽了,新公司使用了 AOP 相关的技术,于是查点资料,复习一下 ...
- java aop面向切面编程
最近一直在学java的spring boot,一直没有弄明白aop面向切面编程是什么意思.看到一篇文章写得很清楚,终于弄明白了,原来跟python的装饰器一样的效果.http://www.cnblog ...
- 【Java】Spring之面向方面编程(AOP)(五)
面向方面编程(AOP)通过提供另一种思考程序结构的方式来补充面向对象编程(OOP).OOP中模块化的关键单元是类,而在AOP中,模块化单元是方面.方面实现了跨越多种类型和对象的关注点(例如事务管理)的 ...
- 吴裕雄--天生自然JAVA SPRING框架开发学习笔记:Spring AOP(面向切面编程)
面向切面编程(AOP)和面向对象编程(OOP)类似,也是一种编程模式.Spring AOP 是基于 AOP 编程模式的一个框架,它的使用有效减少了系统间的重复代码,达到了模块间的松耦合目的. AOP ...
随机推荐
- 2.5 Legacy APIs官网剖析(博主推荐)
不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ 2.5 Legacy APIs A more limited legacy prod ...
- HttpUtility.UrlEncode,Server.UrlEncode 的区别
引用: 1.HttpUtility.UrlEncode,HttpUtility.UrlDecode是静态方法,而Server.UrlEncode,Server.UrlDecode是实例方法. 2.Se ...
- vue 刷新当前页面的方式
1.使用window.location.href window.location.replace() window.location.reload() 会出现空白,体验不是很好 2.先进入一个空路由, ...
- BZOJ3926: [Zjoi2015]诸神眷顾的幻想乡(广义后缀自动机)
Description 幽香是全幻想乡里最受人欢迎的萌妹子,这天,是幽香的2600岁生日,无数幽香的粉丝到了幽香家门前的太阳花田上来为幽香庆祝生日. 粉丝们非常热情,自发组织表演了一系列节目给幽香看. ...
- geotools修改shapefile 属性名乱码问题
在GeoServer中文社区的讨论地址为:http://opengeo.cn/bbs/read.php?tid=1701&page=e&#a 使用geotools修改shapefile ...
- Android-ViewPager+Fragment数据更新问题
由于FragmentPagerAdapter内部存在缓存.因此调用notifyDataSetChanged()并不可以去更新Fragment的内容. 參考:http://www.devba.com/i ...
- 【MongoDB】The connection between two tables
In mongoDB, there are two general way to connect with two tables. Manual Connection and use DBRef 1. ...
- 第二十八天 月出惊山鸟 —Spring的AOP
6月13日,阴转细雨."人闲桂花落.夜静春山空. 月出惊山鸟.时鸣春涧中." 无论在面向过程还是在面向对象里,奇妙的"纯"字,似乎永远都充满了无限的可能性.除了 ...
- 中英文对照 —— 标点符号(punctuation)
有限的几个: What Are the Fourteen Punctuation Marks in English Grammar? period:句号:comma:逗号:冒号:colon:分号:se ...
- POJ 3723 Conscription MST
http://poj.org/problem?id=3723 题目大意: 需要征募女兵N人,男兵M人,没征募一个人需要花费10000美元,但是如果已经征募的人中有一些关系亲密的人,那么可以少花一些钱, ...