理解AOP
http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html
Aspect Oriented Programming 面向切面编程。解耦是程序员编码开发过程中一直追求的。AOP也是为了解耦所诞生。
具体思想是:定义一个切面,在切面的纵向定义处理方法,处理完成之后,回到横向业务流。
AOP 在Spring框架中被作为核心组成部分之一,的确Spring将AOP发挥到很强大的功能。最常见的就是事务控制。工作之余,对于使用的工具,不免需要了解其所以然。学习了一下,写了些程序帮助理解。
AOP 主要是利用代理模式的技术来实现的。
1、静态代理:就是设计模式中的proxy模式
a、业务接口

- /**
- * 抽象主题角色:声明了真实主题和代理主题的共同接口。
- *
- * @author yanbin
- *
- */
- public interface ITalk {
- public void talk(String msg);
- }

b、业务实现

- /**
- * 真实主题角色:定义真实的对象。
- *
- * @author yanbin
- *
- */
- public class PeopleTalk implements ITalk {
- public String username;
- public String age;
- public PeopleTalk(String username, String age) {
- this.username = username;
- this.age = age;
- }
- public void talk(String msg) {
- System.out.println(msg + "!你好,我是" + username + ",我年龄是" + age);
- }
- public String getName() {
- return username;
- }
- public void setName(String name) {
- this.username = name;
- }
- public String getAge() {
- return age;
- }
- public void setAge(String age) {
- this.age = age;
- }
- }

c、代理对象

- /**
- * 代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。
- *
- * @author yanbin
- *
- */
- public class TalkProxy implements ITalk {
- private ITalk talker;
- public TalkProxy(ITalk talker) {
- // super();
- this.talker = talker;
- }
- public void talk(String msg) {
- talker.talk(msg);
- }
- public void talk(String msg, String singname) {
- talker.talk(msg);
- sing(singname);
- }
- private void sing(String singname) {
- System.out.println("唱歌:" + singname);
- }
- }

d、测试类

- /**
- * 代理测试类,使用代理
- *
- * @author yanbin
- *
- */
- public class ProxyPattern {
- public static void main(String[] args) {
- // 不需要执行额外方法的。
- ITalk people = new PeopleTalk("AOP", "18");
- people.talk("No ProXY Test");
- System.out.println("-----------------------------");
- // 需要执行额外方法的(切面)
- TalkProxy talker = new TalkProxy(people);
- talker.talk("ProXY Test", "代理");
- }
- }

从这段代码可以看出来,代理模式其实就是AOP的雏形。 上端代码中talk(String msg, String singname)是一个切面。在代理类中的sing(singname)方法是个后置处理方法。
这样就实现了,其他的辅助方法和业务方法的解耦。业务不需要专门去调用,而是走到talk方法,顺理成章的调用sing方法
再从这段代码看:1、要实现代理方式,必须要定义接口。2、每个业务类,需要一个代理类。
2、动态代理:jdk1.5中提供,利用反射。实现InvocationHandler接口。
业务接口还是必须得,业务接口,业务类同上。
a、代理类:

- /**
- * 动态代理类
- *
- * @author yanbin
- *
- */
- public class DynamicProxy implements InvocationHandler {
- /** 需要代理的目标类 */
- private Object target;
- /**
- * 写法固定,aop专用:绑定委托对象并返回一个代理类
- *
- * @param delegate
- * @return
- */
- public Object bind(Object target) {
- this.target = target;
- return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
- }
- /**
- * @param Object
- * target:指被代理的对象。
- * @param Method
- * method:要调用的方法
- * @param Object
- * [] args:方法调用时所需要的参数
- */
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Object result = null;
- // 切面之前执行
- System.out.println("切面之前执行");
- // 执行业务
- result = method.invoke(target, args);
- // 切面之后执行
- System.out.println("切面之后执行");
- return result;
- }
- }

b、测试类

- /**
- * 测试类
- *
- * @author yanbin
- *
- */
- public class Test {
- public static void main(String[] args) {
- // 绑定代理,这种方式会在所有的方法都加上切面方法
- ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk());
- iTalk.talk("业务说明");
- }
- }

输出结果会是:
切面之前执行
people talk业务说法
切面之后执行
说明只要在业务调用方法切面之前,是可以动态的加入需要处理的方法。
从代码来看,如果再建立一个业务模块,也只需要一个代理类。ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk()); 将业务接口和业务类绑定到动态代理类。
但是这种方式:还是需要定义接口。
3、利用cglib
CGLIB是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强。采用的是继承的方式。不细说,看使用
a、业务类

- /**
- * 业务类
- *
- * @author yanbin
- *
- */
- public class PeopleTalk {
- public void talk(String msg) {
- System.out.println("people talk" + msg);
- }
- }

b、cglib代理类

- /**
- * 使用cglib动态代理
- *
- * @author yanbin
- *
- */
- public class CglibProxy implements MethodInterceptor {
- private Object target;
- /**
- * 创建代理对象
- *
- * @param target
- * @return
- */
- public Object getInstance(Object target) {
- this.target = target;
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(this.target.getClass());
- // 回调方法
- enhancer.setCallback(this);
- // 创建代理对象
- return enhancer.create();
- }
- @Override
- public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- Object result = null;
- System.out.println("事物开始");
- result = methodProxy.invokeSuper(proxy, args);
- System.out.println("事物结束");
- return result;
- }
- }

c.测试类

- /**
- * 测试类
- *
- * @author yanbin
- *
- */
- public class Test {
- public static void main(String[] args) {
- PeopleTalk peopleTalk = (PeopleTalk) new CglibProxy().getInstance(new PeopleTalk());
- peopleTalk.talk("业务方法");
- peopleTalk.spreak("业务方法");
- }
- }

最后输出结果:
事物开始
people talk业务方法
事物结束
事物开始
spreak chinese业务方法
事物结束
由于篇幅有限,这篇主要对AOP的原理简单实现做了演示和阐述,有助自己理解。至于Spring的AOP实现上面无外乎其右,不过实现方面复杂的多。
理解AOP的更多相关文章
- 轻松理解AOP思想(面向切面编程)
本文旨在帮助还没有理解AOP的童鞋看透弄懂AOP,也欢迎高手批评指正. 先说一个Spring是什么吧,大家都是它是一个框架,但框架这个词对新手有点抽象,以致于越解释越模糊,不过它确实是个框架的,但那是 ...
- 简单直白的去理解AOP,了解Spring AOP,使用 @AspectJ - 读书笔记
AOP = Aspect Oriental Programing 面向切面编程 文章里不讲AOP术语,什么连接点.切点.切面什么的,这玩意太绕,记不住也罢.旨在以简单.直白的方式理解AOP,理解Sp ...
- 简单理解AOP(面向切面编程)
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP与OOP是面向不同领域的两种设计思想. ...
- 浅谈Spring AOP 面向切面编程 最通俗易懂的画图理解AOP、AOP通知执行顺序~
简介 我们都知道,Spring 框架作为后端主流框架之一,最有特点的三部分就是IOC控制反转.依赖注入.以及AOP切面.当然AOP作为一个Spring 的重要组成模块,当然IOC是不依赖于Spring ...
- 七、Spring之深入理解AOP源码
Spring之深入理解AOP源码 在上一篇博文中,我们对AOP有了初步的了解,那么接下来我们就对AOP的实现原理进行深入的分析. 在之前写的那个AOP示例代码当中有这样一个注解:@Enable ...
- 深入理解AOP
引子: AOP(面向方面编程:Aspect Oriented Programing)和IoC一样是Spring容器的内核,声明式事务的功能在此基础上开花结果.但是AOP和OOP差别较大,要很好地理解这 ...
- 轻松理解AOP问题
先说一个Spring是什么吧,大家都是它是一个框架,但框架这个词对新手有点抽象,以致于越解释越模糊,不过它确实是个框架的,但那是从功能的角度来定义的,从本质意义上来讲,Spring是一个库,一个Jav ...
- 理解AOP思想(面向切面编程)
AOP:面向切面编程,相信很多刚接触这个词的同行都不是很明白什么,百度一下看到下面这几句话: 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预 ...
- [转]轻松理解AOP思想(面向切面编程)
原文链接 Spring是什么 先说一个Spring是什么吧,大家都是它是一个框架,但框架这个词对新手有点抽象,以致于越解释越模糊,不过它确实是个框架的,但那是从功能的角度来定义的,从本质意义上来讲,S ...
随机推荐
- 3D Touch集成过程整理
1.集成App图标按压快速打开某个功能 在AppDelegate.m中加入以下三个东西 在启动方法里加入3D Touch菜单 - (BOOL)application:(UIApplication *) ...
- Navicat(连接) -1之HTTP 设置
HTTP 设置 HTTP 通道是一种连接到服务器的方法,使用与网络服务器相同的通讯协定(http://)和相同的端口(端口 80).这是当你的互联网服务供应商不允许直接连接,但允许创建 HTTP 连接 ...
- linux下开启mysql慢查询,分析查询语句
一,为什么要开启这个查询呢? 数据库是很容易产生瓶颈的地方,现在Nosql大家讨论这么热,估计都被数据库搞郁闷了.mysql中最影响速度的就是那些查询非常慢的语句,这些慢的语句,可能是写的不够合理或者 ...
- SpringBoot之springfox(Swagger) (ApiDoc接口文档)
Springfox的前身是swagger-springmvc,是一个开源的API doc框架,可以将我们的Controller的方法以文档的形式展现,基于Swagger. 官网地址:http://sp ...
- tar打包排除某个目录
tar zcvf fd.tar.gz * --exclude=file1 --exclude=dir1 注意: 1.--exclude=file1 而不是 --exclude file1 2.要排除一 ...
- 使用php添加定时任务
1. php执行外部命令的函数: system(),exec(),passthru() 注意点: 1.调用的路径,相对路径有时候不是很靠谱. sys ...
- 在IIS8添加WCF服务支持
最近在做Silverlight,Windows Phone应用移植到Windows 8平台,在IIS8中测试一些传统WCF服务应用,发现IIS8不支持WCF服务svc请求,后来发现IIS8缺少对WCF ...
- Home not found. Define system property "openfireHome" or create and add the openfire_init.xml file to the classpath
启动openfire后出现这个错误,貌似什么配置没对吧.网上搜索了下,找到解决办法, $ vi /etc/profile在里面加入:export openfireHome=/opt/openfire ...
- 【MySQL】InnoDB: Error: checksum mismatch in data file 报错
参考:http://www.jb51.net/article/66951.htm 用5.7版本启动原5.5实例后,再用5.5启动出现以下报错 InnoDB: Error: checksum misma ...
- sqoop1.99.6 update导出语句
我们采用sqoop-export插入数据的时候,如果主键已经存在了,插入会失败.想要根据主键判断是否要进行insert操作还是update操作,sqoop提供了update语法.示例 sqoop -- ...