Java 动态代理及AOP实现机制
AOP实现机制
http://www.iteye.com/topic/1116696
AOP: (Aspect Oriented Programming) 面向切面编程
AOP包括切面(aspect)、通知(advice)、连接点(joinpoint),实现方式就是通过对目标对象的代理在连接点前后加入通知,完成统一的切面操作
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。主要的功能是:日志记录,性能统计,安全控制,事务处理,异常处理等等。
面向接口编程,(横向编程)
AOP的底层实现-CGLIB动态代理和JDK动态代理
http://blog.csdn.net/dreamrealised/article/details/12885739
AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础。它是一种面向切面编程的思想。关于AOP的基础知识,相信多数童鞋都已经了如指掌,我们就略过这部分,来讲解下AOP的核心功能的底层实现机制:如何用动态代理来实现切面拦截。
AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。
那么动态代理是如何实现将切面逻辑(advise)织入到目标类方法中去的呢?下面我们就来详细介绍并实现AOP中用到的两种动态代理。
AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。两种方法同时存在,各有优劣。
jdk动态代理是由java内部的反射机制来实现的,
cglib动态代理底层则是借助asm来实现的。
总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势。
一、jdk动态代理实现AOP拦截(代码中的关键地方都添加了注释)
1、为目标类(target)定义统一的接口类Service,这个是jdk动态代理必须的前提。
package jdkproxy; /**
* 该类是所有被代理类的接口类,jdk实现的代理要求被代理类基于统一的接口
*
*/
public interface Service {
/**
* add方法
*/
public void add(); /**
* update方法
*/
public void update();
}
2、目标类AService,我们的实验目标就是在AService中add和update方法的前后实现拦截,加入自定义切面逻辑advise
package jdkproxy; /**
* 被代理类,即目标类target
*
*
*/
public class AService implements Service {
/*
* (non-Javadoc)
*
* @see jdkproxy.Service#add()
*/
public void add() {
System.out.println("AService add>>>>>>>>>>>>>>>>>>");
} /*
* (non-Javadoc)
*
* @see jdkproxy.Service#update()
*/
public void update() {
System.out.println("AService update>>>>>>>>>>>>>>>");
}
}
3、实现动态代理类MyInvocationHandler,实现InvocationHandler接口,并且实现接口中的invoke方法。仔细看invoke方法,就是在该方法中加入切面逻辑的。目标类方法的执行是由mehod.invoke(target,args)这条语句完成。
package jdkproxy; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler {
private Object target; MyInvocationHandler() {
super();
} MyInvocationHandler(Object target) {
super();
this.target = target;
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 程序执行前加入逻辑,MethodBeforeAdviceInterceptor
System.out.println("before-----------------------------");
// 程序执行
Object result = method.invoke(target, args);
// 程序执行后加入逻辑,MethodAfterAdviceInterceptor
System.out.println("after------------------------------");
return result;
} }
4、测试类,其中增强的目标对象是由Proxy.newProxyInstance(aService.getClass().getClassLoader(), aService.getClass().getInterfaces(), handler);来生成的。
package jdkproxy; import java.lang.reflect.Proxy; public class Test {
public static void main(String[] args) {
Service aService = new AService();
MyInvocationHandler handler = new MyInvocationHandler(aService);
// Proxy为InvocationHandler实现类动态创建一个符合某一接口的代理实例
Service aServiceProxy = (Service) Proxy.newProxyInstance(aService
.getClass().getClassLoader(), aService.getClass()
.getInterfaces(), handler);
// 由动态生成的代理对象来aServiceProxy 代理执行程序,其中aServiceProxy 符合Service接口
aServiceProxy.add();
System.out.println();
aServiceProxy.update();
// 以下是对B的代理
// Service bService = new BService();
// MyInvocationHandler handler = new MyInvocationHandler(bService);
// Service bServiceProxy = (Service) Proxy.newProxyInstance(bService
// .getClass().getClassLoader(), bService.getClass()
// .getInterfaces(), handler);
// bServiceProxy.add();
// System.out.println();
// bServiceProxy.update();
}
}
自此,jdk动态代理来实现AOP拦截机制的代码已经实现,下面我们看一下拦截的结果,程序输出结果如下:
before-----------------------------
AService add>>>>>>>>>>>>>>>>>>
after------------------------------
before-----------------------------
AService update>>>>>>>>>>>>>>>
after------------------------------
可以看到,在目标类AService的add和update方法前后已经加入了自定义的切面逻辑,AOP拦截机制生效了。
二、cglib动态代理实现AOP拦截(代码中的关键地方都添加了注释)
1、目标类,cglib不需要定义目标类的统一接口
package cglibproxy; /**
* 被代理类,即目标对象target
*
*/
public class Base {
/**
* 一个模拟的add方法
*/
public void add() {
System.out.println("add ------------");
}
}
2、实现动态代理类CglibProxy,需要实现MethodInterceptor接口,实现intercept方法。
该代理中在add方法前后加入了自定义的切面逻辑,目标类add方法执行语句为proxy.invokeSuper(object, args);
package cglibproxy; import java.lang.reflect.Method;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; /**
* 此为代理类,用于在pointcut处添加advise
*
*
*/
public class CglibProxy implements MethodInterceptor { public Object intercept(Object object, Method method, Object[] args,
MethodProxy proxy) throws Throwable {
// 添加切面逻辑(advise),此处是在目标类代码执行之前,即为MethodBeforeAdviceInterceptor。
System.out.println("before-------------");
// 执行目标类add方法
proxy.invokeSuper(object, args);
// 添加切面逻辑(advise),此处是在目标类代码执行之后,即为MethodAfterAdviceInterceptor。
System.out.println("after--------------");
return null;
} }
3、获取增强的目标类的工厂Factory,其中增强的方法类对象是有Enhancer来实现的,代码如下所示:
package cglibproxy; import net.sf.cglib.proxy.Enhancer; /**
* 工厂类,生成增强过的目标类(已加入切入逻辑)
*
*/
public class Factory {
/**
* 获得增强之后的目标类,即添加了切入逻辑advice之后的目标类
*
* @return
*/
public static Base getInstance(CglibProxy proxy) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Base.class);
//回调方法的参数为代理类对象CglibProxy,最后增强目标类调用的是代理类对象CglibProxy中的intercept方法
enhancer.setCallback(proxy);
// 此刻,base不是单纯的目标类,而是增强过的目标类
Base base = (Base) enhancer.create();
return base;
}
}
4、测试类
package cglibproxy; public class Test {
public static void main(String[] args) {
CglibProxy proxy = new CglibProxy();
// base为生成的增强过的目标类
Base base = Factory.getInstance(proxy);
base.add();
}
}
自此,cglib动态代理实现的AOP拦截机制已经基本实现,下面我们来看一下拦截的效果如何,程序执行结果如下:
before-------------
add ------------
after--------------
可以看到,在目标类Base的add方法前后已经加入了自定义的切面逻辑,AOP拦截机制生效了。
此外,需要说明一下的是,cglib动态代理用到了第三方类库,需要在项目中引入两个jar包:cglib.jar和asm.jar。稍后会在csdn资源中上传这两个jar包。免积分的啊。
jar包和相关代码请见http://download.csdn.net/detail/dreamrealised/6427885
总之,AOP的核心机制和基本功能已经能够通过动态代理来实现了,至于AOP中,如何从配置文档中得到目标类target、advisor的bean,如何判断拦截器类型等问题,就借助于Spring中另一个核心IOC来解决了,后续会有IOC的核心实现机制讲解。
Java 动态代理及AOP实现机制的更多相关文章
- Java动态代理-->Spring AOP
引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓“登高必自卑,涉远必自迩”.以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系列分别介绍这些Jav ...
- Java 动态代理与AOP
动态代理与AOP 代理模式 代理模式给某一个目标对象(target)提供代理对象(proxy),并由代理对象控制对target对象的引用. 模式图: 代理模式中的角色有: 抽象对象角色(Abstrac ...
- [JAVA]动态代理与AOP的千丝万缕
动态代理与AOP的联系 别的不说,直接上图 首先是AOP切面编程 什么是切面?(自己心里想想就ok)所以所谓的切面编程,你也就懂得大体了,只是这个被切的是个程序而已 那么AOP与动态代理有什么关系呢? ...
- Java动态代理(AOP)
目录 一.代理 1. 什么是代理? 2. 使用代理模式的作用 3. 实现代理的方式 二.静态代理 1. 模拟用户购买u盘 2. 静态代理的缺点 三.动态代理 四. JDK 动态代理 1. Invoca ...
- 转:Java 动态代理的内部实现机制(大体意思正确,写的还行的一篇文章)
转:Java动态绑定的内部实现机制 JAVA虚拟机调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法.相反,当虚拟机调用一个实例方法时,它会基于对象实际 的类型(只能在运行 ...
- Java 动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
- java动态代理实现与原理详细分析(代码层面解释了AOP的实现)
关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式 代理模式是常用的java设计模式, ...
- AOP面向切面编程JAVA动态代理实现用户权限管理(实现篇)
java动态代理机制的功能十分强大,使用动态代理技术能够有效的降低应用中各个对象之间的耦合紧密程度,提高开发的效率以及程序的可维护性,事实上Spring AOP就是建立在Java动态代理的基础之上.其 ...
- 深入理解 Java 动态代理机制
Java 有两种代理方式,一种是静态代理,另一种是动态代理.对于静态代理,其实就是通过依赖注入,对对象进行封装,不让外部知道实现的细节.很多 API 就是通过这种形式来封装的. 代理模式结构图(图片来 ...
随机推荐
- 图解NuGet服务器搭建和使用过程
听语音 浏览:0 | 更新:2017-10-31 09:13 | 标签:服务器 1 2 3 4 5 6 7 分步阅读 本篇经验将和大家介绍内网搭建NuGet服务器的步骤,希望对大家的工作和学习有所帮助 ...
- pip install mysql_python报错解决办法
首先请注意,mysql_python只支持Python2,所以假如你是python3,就直接用python-connector去吧.下面这一条命令就可以了 pip install mysql-conn ...
- ESP8266-向物联网云平台发送数据--dweet
方法一: //向物联网平台发送数据 //发送数据格式: https://dweet.io/dweet/for/my-thing-name?hello=world 免费平台 //my-thing-nam ...
- java获取当前时间的年周月季度等的开始结束时间
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; /** * Created b ...
- VGA驱动时序说明
根据不同的显示器分辨率,需要不同的刷新频率. 其中显示模式中@60表示显示器1秒钟刷新60帧. 其中时钟(MHz),表示FPGA输出给显示器的时钟频率.需要我们配置PLL的时钟频率为对应频率. 其中行 ...
- Linux内核设计与实现 总结笔记(第十六章)页高速缓存和页回写
页高速缓存是Linux内核实现磁盘缓存.磁盘告诉缓存重要源自:第一,访问磁盘的速度要远远低于访问内存. 第二,数据一旦被访问,就很有可能在短期内再次被访问到.这种短时期内集中访问同一片数据的原理称作临 ...
- Java——动态绑定和多态
动态绑定是在执行期间(而不是编译期间)判断所用对象的实际类型,根据其实际的类型调用其相应的方法(确定选择哪个多态形式被调用). 首先是方法的参数是父类对象,传入子类对象是否可行 然后引出Parent ...
- 牛飞盘队Cow Frisbee Team
老唐最近迷上了飞盘,约翰想和他一起玩,于是打算从他家的N头奶牛中选出一支队伍. 每只奶牛的能力为整数,第i头奶牛的能力为R i .飞盘队的队员数量不能少于 .大于N. 一支队伍的总能力就是所有队员能力 ...
- 【Python】selenium模拟淘宝登录
# -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.common.by import By f ...
- UITabbarController & UITabbar 学习
最后更新2016-04-06 一. UITabbarController 给UITabbarController 设置viewControllers熟悉时候,超过五个就会有一个 moreNavigat ...