InvocationHandler
【Spring AOP的底层实现技术 Proxy InvocationHandler】【 http://blog.csdn.net/sup_heaven/article/details/6898292 】
【动态代理模式】分离横切关注点
InvocationHandler反射机制:java.lang.reflect.Method,java.lang.reflact.Proxy
InvocationHandler:
【AOP代理对象的生成】
两种方式:JDK Proxy代理接口,CGLib扩展类。
JdkDynamicAopProxy类:创建代理,Proxy.newProxyInstance( classLoader, proxiedInterfaces, this );
上面我们看到了在Spring中通过ProxyFactoryBean实现AOP功能的第一步,得到AopProxy代理对象的基本过程,以及通过使用 JDK和CGLIB最终产生AopProxy代理对象的实现原理。下面我们看看AopProxy代理对象的拦截机制是怎样发挥作用和实现AOP功能的。在 JdkDynamicAopProxy中生成Proxy对象时,我们回顾一下它的AopProxy代理对象的生成调用,如下所示。
- Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
这 里的this参数对应的是InvocationHandler对象,InvocationHandler是JDK定义的反射类的一个接口,这个接口定义了 invoke方法,而这个invoke方法是作为JDKProxy代理对象进行拦截的回调入口出现的。我们看到,在JdkDynamicAopProxy 实现了InvocationHandler接口,也就是说当Proxy对象的代理方法被调用时,JdkDynamicAopProxy的invoke方法作为Proxy对象的回调函数而被触发,从而通过invoke的具体实现,来完成对目标对象方法调用的拦截或者说功能增强的工作。
下 面我们看看JdkDynamicAopProxy的invoke方法实现,如代码清单3-18所示。可以看到,对Proxy对象完成的代理设置是在 invoke方法中完成的,这些设置包括获取目标对象、拦截器链,同时把这些对象作为输入,创建了ReflectiveMethodInvocation 对象,通过这个ReflectiveMethodInvocation对象来完成对AOP功能实现的封装。
在这个invoke方法中,包含了一个完整的拦截器链对目标对象的拦截过程,比如获得拦截器链并对其中的拦截器进行配置,逐个运行拦截器链里的拦截增强,直到最后对目标对象方法的运行,等等。
代码清单3-18 AopProxy代理对象的回调
- public Object invoke(Object proxy, Method method, Object[]
- args) throws Throwable {
- MethodInvocation invocation = null;
- Object oldProxy = null;
- boolean setProxyContext = false;
- TargetSource targetSource =
- this.advised.targetSource;
- Class targetClass = null;
- Object target = null;
- try {
- if (!this.equalsDefined &&
- AopUtils.isEqualsMethod(method)) {
- // The target does not implement the
- equals(Object) method itself.
- return equals(args[0]);
- }
- if (!this.hashCodeDefined &&
- AopUtils.isHashCodeMethod(method)) {
- // The target does not implement the
- hashCode() method itself.
- return hashCode();
- }
- if (!this.advised.opaque &&
- method.getDeclaringClass().isInterface() &&
- method.getDeclaringClass().isAssignableFrom(Advised.class))
- {
- // Service invocations on
- ProxyConfig with the proxy config...
- return
- AopUtils.invokeJoinpointUsingReflection(this.advised,
- method, args);
- }
- Object retVal = null;
- if (this.advised.exposeProxy) {
- // Make invocation available if
- necessary.
- oldProxy =
- AopContext.setCurrentProxy(proxy);
- setProxyContext = true;
- }
- /**
- * May be null. Get as late as possible to
- minimize the time we "own" the
- * target, in case it comes from a pool.
- */
- //得到目标对象的地方。
- target = targetSource.getTarget();
- if (target != null) {
- targetClass = target.getClass();
- }
- // Get the interception chain for this
- method.
- // 这里获得定义好的拦截器链。
- List<Object> chain =
- this.advised.getInterceptorsAndDynamicInterception
- Advice(method, targetClass);
- /**
- * Check whether we have any advice. If we
- don't, we can fallback on
- * direct reflective invocation of the
- target, and avoid creating a MethodInvocation.
- */
- //
- 如果没有设定拦截器,那么我们就直接调用target的对应方法。
- if (chain.isEmpty()) {
- /**
- * We can skip creating a
- MethodInvocation: just invoke the target directly
- * Note that the final invoker must
- be an InvokerInterceptor so we
- * know it does nothing but a
- reflective operation on the target, and no hot
- * swapping or fancy proxying.
- */
- retVal =
- AopUtils.invokeJoinpointUsingReflection(target, method,
- args);
- }
- else {
- // We need to create a method
- invocation...
- /**
- *
- 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相
- 应方法,
- *
- 通过构造一个ReflectiveMethodInvocation来实现,下面我们会看
- *
- 这个ReflectiveMethodInvocation类的具体实现。
- */
- invocation = new
- ReflectiveMethodInvocation(proxy, target, method,
- args, targetClass, chain);
- // Proceed to the joinpoint through
- the interceptor chain.
- //沿着拦截器链继续前进。
- retVal = invocation.proceed();
- }
- // Massage return value if necessary.
- if (retVal != null && retVal == target &&
- method.getReturnType().
- isInstance(Proxy) &&
- !RawTargetAccess.class.isAssignableFrom
- (method.getDeclaringClass())) {
- /**
- * Special case: it returned "this"
- and the return type of the method
- * is type-compatible. Note that we
- can't help if the target sets
- * a reference to itself in another
- returned object.
- */
- retVal = Proxy;
- }
- return retVal;
- }
- finally {
- if (target != null &&
- !targetSource.isStatic()) {
- // Must have come from TargetSource.
- targetSource.releaseTarget(target);
- }
- if (setProxyContext) {
- // Restore old proxy.
- AopContext.setCurrentProxy(oldProxy);
- }
- }
- }
InvocationHandler的更多相关文章
- java中InvocationHandler 用于实现代理。
以下的内容部分参考了网络上的内容,在此对原作者表示感谢! Java中动态代理的实现,关键就是这两个东西:Proxy.InvocationHandler,下面从InvocationHandler接口中的 ...
- java 动态代理范例 InvocationHandler与Proxy
java 动态代理范例 InvocationHandler与Proxy,拦截与代理 java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxy ...
- java 动态代理深度学习(Proxy,InvocationHandler),含$Proxy0源码
java 动态代理深度学习, 一.相关类及其方法: java.lang.reflect.Proxy,Proxy 提供用于创建动态代理类和实例的静态方法.newProxyInstance()返回一个指定 ...
- java 动态代理学习(Proxy,InvocationHandler)
前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里 ...
- 动态代理 Proxy InvocationHandler
前奏 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常 ...
- InvocationHandler中invoke()方法的调用问题
转InvocationHandler中invoke()方法的调用问题 Java中动态代理的实现,关键就是这两个东西:Proxy.InvocationHandler,下面从InvocationHandl ...
- Proxy是在什么时候调用InvocationHandler的invoke方法的
最近看到spring的动态代理,扒到深处看到时 Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);看到这一句,顿时比较懵逼,还是 ...
- 基于接口的 InvocationHandler 动态代理(换种写法)
InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each p ...
- InvocationHandler和Proxy(Class)的动态代理机制详解
在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...
随机推荐
- C++ 编写Windows service
最近实现一个windows server端守护进程启动服务功能(c++实现),遇到了一些问题,记录一下 1. 启动Service实现代码: int _tmain(int argc, TCHAR* ar ...
- 使用 foreach 操作数组
foreach 并不是 Java 中的关键字,是 for 语句的特殊简化版本,在遍历数组.集合时, foreach 更简单便捷.从英文字面意思理解 foreach 也就是“ for 每一个”的意思,那 ...
- 在python中如何设置当前工作目录
import osos.chdir('要设置的当前目录') >>> import os >>> os.getcwd() 'D:\\Python27' >> ...
- struts2 action 返回图片流
数据库为mssql zp字段为image类型 java代码 OutputStream out = null; try { String contenttype = "image/jpeg&q ...
- js中判断是不是数字
使用isaNa来进行判断,这个函数的底层实现是:Nunmber,如果经过转化是数字则返回false,否则返回true Number('100px')返回的是ANA,parseInt('100px')返 ...
- 【,net】发布网站问题
今天解决了一个发布后网站访问不了的问题: 问题: 发布网站:http://172.168.1.102:2222/nologin.html,但是页面一直处于刷新状态,进行不了系统: 解决方法: 问开发他 ...
- linux_2015_0827_linux中一些常用词的发音and…
linux相关 Unix: [ ju:niks ] 发音 (yew-nicks) 尤里克斯 GNU [ gəˈnju: ] 发音 (guh-noo) 葛扭 Linux: [ 'li:nэks ] 里那 ...
- C# 实现无焦点窗体(转载)
#region 无焦点窗体 [System.Runtime.InteropServices.DllImport("user32.dll")] private extern stat ...
- C语言实现strcpy
strcpy.h: #ifndef STRCPY_H #define STRCPY_H #include <stdio.h> char *cat_strcpy(char *dst, con ...
- Python的descriptor (2)
前面说了descriptor,这个东西其实和Java的setter,getter有点像.但这个descriptor和上文中我们开始提到的函数方法这些东西有什么关系呢? 所有的函数都可以是descrip ...