- 浏览: 381053 次
- 性别:
文章分类
最新评论
-
wjw103:
You are using old notation for ...
Struts2 入门实例代码 -
hhb19900618:
你好 你这个工程压缩包是不是有问题啊?根本不能导入?
Struts2 入门实例代码 -
it爱:
[list][*]dsadsa[*]dsadsa[*]dsad ...
Spring AOP 学习小结 -
youjianbo_han_87:
和 weblogic 有个毛线关系???????
Weblogic下的自动任务 -
hua839:
是用SmartUpload进行文件上传
用Spring大概有3个月,一直都是张口AOP,闭口AOP,但是Spring的AOP具体是怎么实现的,现在也不是十分清楚.
只知道可以用JDK的动态代理,基于接口,或者是cglib方式字节码增强.目前对JDK的动态代理方式不是很理解,固拿出来探讨下,我知道这应该是个新手贴,但还是请大家给点意见.如果真正理解了动态代理,那么对基于Spring AOP出现的各种现象就比较容易理解了.
先贴上一段代码.
从以上代码可以看出在调用com.makeCar()的时候动态代理会生效,而在makeCar()方法中调用abc()的时候并不会进行动态代理.
猜测到底JDK是如何实现动态代理的?
1.基于JDK的反射机制,通过JDK调用handler的method.invoke(this.com, new Class[] {});实现对最终方法的调用,前后各有代码也有点Decorator的味道!
2.也是我比较模糊的一点
也就是动态代理JDK到底是如何实现的?
JDK的动态代理并没有生成具体的类,她只是在运行中起动态调用目标类的作用,那么代码
究竟做了什么,是将CarCompany注册到JDK的某个地方,当调用com.makeCar()的时候JDK到注册的地方去寻找,发现有注册就进行动态代理?
哦,这个说了。。。
多谢楼上,看来我的猜测是对的!
这样来说,对于Spring AOP来说,比如事务拦截的时候,只拦截某些方法,实际上Spring 应该是在类似如下代码做文章!
如果以上说法成立,那么实际上对于已经被动态代理的接口来讲,无论方法是否匹配,都是通过java的反射机制来对目标类实现调用的.
也就是说一个interface有10个方法声明,但是我只对其中一个方法配置事务属性,结果是对该接口的所有方法调用均是通过发射机制完成的,当然对其中配置事务属性的方法进行事务拦截.
PS:楼上给的blog地址是你自己的blog吗?
只知道可以用JDK的动态代理,基于接口,或者是cglib方式字节码增强.目前对JDK的动态代理方式不是很理解,固拿出来探讨下,我知道这应该是个新手贴,但还是请大家给点意见.如果真正理解了动态代理,那么对基于Spring AOP出现的各种现象就比较容易理解了.
先贴上一段代码.
package com.jamesby.proxy; public interface CarCompany { public void makeCar(); public void abc(); } package com.jamesby.proxy; public class CarCompanyImpl implements CarCompany { public void makeCar() { System.out.println("Company A make a car!"); abc(); } public void abc() { System.out.println("abc is invoked!"); } } package com.jamesby.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class CarCompanyHandler implements InvocationHandler { CarCompany com; public CarCompanyHandler(CarCompany com) { this.com = com; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("time1:" + System.currentTimeMillis()); method.invoke(this.com, new Class[] {}); System.out.println("time2:" + System.currentTimeMillis()); return null; } } package com.jamesby.proxy; import java.lang.reflect.Proxy; public class Test { public static void main(String[] arg) { CarCompanyImpl a = new CarCompanyImpl(); CarCompanyHandler handler = new CarCompanyHandler(a); // 产生一个新的代理类 CarCompany com = (CarCompany) Proxy.newProxyInstance(Test.class .getClassLoader(), new Class[] { CarCompany.class }, handler); com.makeCar(); } }
从以上代码可以看出在调用com.makeCar()的时候动态代理会生效,而在makeCar()方法中调用abc()的时候并不会进行动态代理.
猜测到底JDK是如何实现动态代理的?
1.基于JDK的反射机制,通过JDK调用handler的method.invoke(this.com, new Class[] {});实现对最终方法的调用,前后各有代码也有点Decorator的味道!
2.也是我比较模糊的一点
CarCompany com = (CarCompany) Proxy.newProxyInstance(Test.class .getClassLoader(), new Class[] { CarCompany.class }, handler); com.makeCar();
也就是动态代理JDK到底是如何实现的?
JDK的动态代理并没有生成具体的类,她只是在运行中起动态调用目标类的作用,那么代码
CarCompany com = (CarCompany) Proxy.newProxyInstance(Test.class .getClassLoader(), new Class[] { CarCompany.class }, handler);
究竟做了什么,是将CarCompany注册到JDK的某个地方,当调用com.makeCar()的时候JDK到注册的地方去寻找,发现有注册就进行动态代理?
评论
10 楼
shaucle
2007-04-15
yimlin 写道
正解!
http://www.blogjava.net/AndersLin/archive/2006/06/11/51997.html
http://www.blogjava.net/AndersLin/archive/2006/06/11/51997.html
哦,这个说了。。。
9 楼
shaucle
2007-04-15
看看jdk动态代理反编译后的<? extends Proxy>
如果有兴趣的话再看看
cglib(asm), javasist
如果有兴趣的话再看看
cglib(asm), javasist
8 楼
jamesby
2007-04-14
janh 写道
应该只有一个动态代理,多个拦截器是由spring自己进行维护的,它有专门处理来根据通知类型和Ordered排序值调用不同的拦截器。
我也是这样一来理解的,在看Spring AOP的代码!
7 楼
janh
2007-04-14
应该只有一个动态代理,多个拦截器是由spring自己进行维护的,它有专门处理来根据通知类型和Ordered排序值调用不同的拦截器。
6 楼
jamesby
2007-04-14
还有一个问题,那就是如果为一个ServiceImpl配置多个拦截器的时候到底生成多少个动态代理类的问题!
一个动态代理类?
如果一个那多个拦截器如何按照次序拦截?
一个动态代理类?
如果一个那多个拦截器如何按照次序拦截?
5 楼
jamesby
2007-04-14
这样就可以很好的理解为什么service调用service本身的方法AOP起不到拦截作用了.
因为Spring 将Service 注入到Controller 或者Action的时候注入的是动态代理类,而service调用service自己的方法这时候的对象句柄this实际上是自己实现ServiceImpl类.因此AOP拦截不到.
因为Spring 将Service 注入到Controller 或者Action的时候注入的是动态代理类,而service调用service自己的方法这时候的对象句柄this实际上是自己实现ServiceImpl类.因此AOP拦截不到.
4 楼
jamesby
2007-04-14
yimlin 写道
正解!
http://www.blogjava.net/AndersLin/archive/2006/06/11/51997.html
http://www.blogjava.net/AndersLin/archive/2006/06/11/51997.html
多谢楼上,看来我的猜测是对的!
这样来说,对于Spring AOP来说,比如事务拦截的时候,只拦截某些方法,实际上Spring 应该是在类似如下代码做文章!
public class CarCompanyHandler implements InvocationHandler { CarCompany com; public CarCompanyHandler(CarCompany com) { this.com = com; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //此处做文章,如果是需要事务拦截的,则此处添加事务代,否则什么也不做. method.invoke(this.com, new Class[] {}); return null; } }
如果以上说法成立,那么实际上对于已经被动态代理的接口来讲,无论方法是否匹配,都是通过java的反射机制来对目标类实现调用的.
也就是说一个interface有10个方法声明,但是我只对其中一个方法配置事务属性,结果是对该接口的所有方法调用均是通过发射机制完成的,当然对其中配置事务属性的方法进行事务拦截.
PS:楼上给的blog地址是你自己的blog吗?
3 楼
yimlin
2007-04-14
正解!
http://www.blogjava.net/AndersLin/archive/2006/06/11/51997.html
http://www.blogjava.net/AndersLin/archive/2006/06/11/51997.html
2 楼
jamesby
2007-04-14
Class cl = getProxyClass(loader, interfaces);
生成实现接口的类,并自动设置一个ContractorMethodName(InvocationHandler h)的构造函数?
如果这样就还有一个问题也是最关键的问题搞不懂.
就是InvocationHandler 的invoke是如何被调用的?是对代理接口的每个声明的方法生成类似如下代码?
生成实现接口的类,并自动设置一个ContractorMethodName(InvocationHandler h)的构造函数?
如果这样就还有一个问题也是最关键的问题搞不懂.
就是InvocationHandler 的invoke是如何被调用的?是对代理接口的每个声明的方法生成类似如下代码?
makeCar() { handler.invoke(......); }
1 楼
jamesby
2007-04-14
先贴段JDK的代码,大家帮助分析下:
package java.lang.reflect; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import sun.misc.ProxyGenerator; public class Proxy implements java.io.Serializable { private static final long serialVersionUID = -2222568056686623797L; private final static String proxyClassNamePrefix = "$Proxy"; private final static Class[] constructorParams ={ InvocationHandler.class }; private static Map loaderToCache = new WeakHashMap(); private static Object pendingGenerationMarker = new Object(); private static long nextUniqueNumber = 0; private static Object nextUniqueNumberLock = new Object(); private static Map proxyClasses =Collections.synchronizedMap(new WeakHashMap()); protected InvocationHandler h; private Proxy() { } protected Proxy(InvocationHandler h) { this.h = h; } //关键是这个方法,正在看. public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } Class proxyClass = null; String[] interfaceNames = new String[interfaces.length]; Set interfaceSet = new HashSet(); // for detecting duplicates for (int i = 0; i < interfaces.length; i++) { String interfaceName = interfaces[i].getName(); Class interfaceClass = null; try { interfaceClass = Class.forName(interfaceName, false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != interfaces[i]) { throw new IllegalArgumentException( interfaces[i] + " is not visible from class loader"); } if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } if (interfaceSet.contains(interfaceClass)) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } interfaceSet.add(interfaceClass); interfaceNames[i] = interfaceName; } Object key = Arrays.asList(interfaceNames); Map cache; synchronized (loaderToCache) { cache = (Map) loaderToCache.get(loader); if (cache == null) { cache = new HashMap(); loaderToCache.put(loader, cache); } } synchronized (cache) { do { Object value = cache.get(key); if (value instanceof Reference) { proxyClass = (Class) ((Reference) value).get(); } if (proxyClass != null) { return proxyClass; } else if (value == pendingGenerationMarker) { try { cache.wait(); } catch (InterruptedException e) { } continue; } else { cache.put(key, pendingGenerationMarker); break; } } while (true); } try { String proxyPkg = null; // package to define proxy class in for (int i = 0; i < interfaces.length; i++) { int flags = interfaces[i].getModifiers(); if (!Modifier.isPublic(flags)) { String name = interfaces[i].getName(); int n = name.lastIndexOf('.'); String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); if (proxyPkg == null) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException( "non-public interfaces from different packages"); } } } if (proxyPkg == null) { // if no non-public proxy interfaces, proxyPkg = ""; // use the unnamed package } { long num; synchronized (nextUniqueNumberLock) { num = nextUniqueNumber++; } String proxyName = proxyPkg + proxyClassNamePrefix + num; byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces); try { proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException(e.toString()); } } proxyClasses.put(proxyClass, null); } finally { synchronized (cache) { if (proxyClass != null) { cache.put(key, new WeakReference(proxyClass)); } else { cache.remove(key); } cache.notifyAll(); } } return proxyClass; } //这个就是我的例子中调用的方法. public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw new NullPointerException(); } Class cl = getProxyClass(loader, interfaces); try { Constructor cons = cl.getConstructor(constructorParams); return (Object) cons.newInstance(new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } } public static boolean isProxyClass(Class<?> cl) { if (cl == null) { throw new NullPointerException(); } return proxyClasses.containsKey(cl); } public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { if (!isProxyClass(proxy.getClass())) { throw new IllegalArgumentException("not a proxy instance"); } Proxy p = (Proxy) proxy; return p.h; } private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len); }
发表评论
-
Spring MVC 的 multipartResolver 不能同iWebOffice2006 共同使用
2007-03-05 12:10 2783项目使用iWebOffice2006,本来可以正常使用,但是系 ... -
Spring MutiActionController实现FormController在Controller中的代码事例
2007-02-12 12:11 2799public ModelAndView handelXqR ... -
关于FastClassByCGLIB$$c8ef9cf1.invoke(<generated>)出错信息的解释
2007-02-09 15:06 15633软件采用SpringMVC+Spring+iBatis进行设计 ... -
Acegi学习小结
2007-01-17 15:34 10252一、基本原理 Acegi认证授权主要基于两大技术,一是Filt ... -
Spring AOP Sample Code
2006-12-25 22:28 5199Before Advice package test3; ... -
Spring AOP 学习小结
2006-12-21 10:10 54750一、AOP 概念 Joinpoint:它定义在哪里加入你的逻 ... -
Spring AOP 部分Class的UML图
2006-12-20 12:08 6127Spring AOP 部分Class的UML -
对Spring的BeanFactory的学习小节
2006-12-16 10:30 3166以下内容是从书中摘录来的,但是我发现即使摘录一遍,对其内容的理 ... -
JdbcTemplate代码的部分使用
2006-12-15 17:20 2536package com.cm.main.dao.impl; ... -
用 MultiActionController 实现 SimpleFormController的部分功能?
2006-12-15 12:11 6330Controller protected BindExcep ... -
为什么我的Spring的声明事务失效了?
2006-12-13 12:10 3656DAO代码如下: public class UserDAO ... -
Spring 声明事务的两种方式-----之一
2006-12-12 20:00 1717<?xml version="1.0" ... -
Spring 声明事务的两种方式-----之二
2006-12-12 19:59 1460<bean id="dataSource&qu ...
相关推荐
模拟JDK动态代理内部实现
实现了一份jdk动态代理的demo,做了详细注释,供以后复习使用,另外,这里为什么需要大于100个字节才能传资源?我就不想那么多不行吗???
JDK动态代理源码下载,动态产生代理,实现对【不同类】,【不同方法】的代理
动态代理是使用jdk的反射机制,创建对象的...jdk动态代理,必须有接口,目标类必须实现接口, 没有接口时,需要使用cglib动态代理。 动态代理可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。
spring aop jdk 动态代理的底层实现解析模拟
AOP之JDK动态代理和CGLib动态代理 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45195383
基于java的jdk动态代理, 比较了静态代理与动态代理的区别,以及动态代理的底层实现,反编译class文件 jdk动态代理和cglib的区别
JAVA动态代理实现Demo(JDK动态代理和CGLIB动态代理)
* * * * JDK动态代理 JDK动态代理 JDK动态代理是通过java.lang.reflect.Proxy 类来实现的,我们可以调用Proxy类的newProxyInstance()方法来创建代理对象。对于使用业务接口的类,Spring默认会使用JDK动态代理来实现...
动态代理::在程序运行时,运用反射机制动态创建而成。 动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为...
JDK动态代理的底层实现原理
分别使用jdk和cglib实现动态代理,包含UML图。还有相关的博客链接:http://blog.csdn.net/y_love_f/article/details/46345581.博客中有具体的代理解释
jdk动态代理使用及实现分析.one
JDK和CGlib分别实现的动态代理源代码
本工程是对静态代理,动态代理的测试,并且实现了对jdk动态代理的简单模拟!
JavaEE JDK动态代理实现AOP切面功能
NULL 博文链接:https://54wangyong.iteye.com/blog/1920998
实现java动态代理的两个实例,jdk动态代理和cglib
代理模式详解-jdk与cglib动态代理与底层实现,spring中常用的设计模式,本案例是从源码到代理模式的实现。
* 动态代理(JDK代理、接口代理、拦截器模式) * 动态代理中的静态方法:java.lang.reflect.Proxy.newProxyInstance (ClassLoader(类加载器),interface(接口),handler(监听处理器)) * * 代码示例:《帮爸爸...