【转载】Java JDK 动态代理(AOP)使用及实现原理分析

转自:http://blog.csdn.net/jiankunking/article/details/52143504

版权声明:作者:jiankunking 出处:http://blog.csdn.net/jiankunking 本文版权归作者和CSDN共有

一、什么是代理?

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。

代理模式UML图:

简单结构示意图:

为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。

二、Java 动态代理类

Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类:

(1)Interface InvocationHandler:该接口中仅定义了一个方法

[java] view plain copy

  1. publicobject invoke(Object obj,Method method, Object[] args)

在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。

(2)Proxy:该类即为动态代理类,其中主要包含以下内容:

protected Proxy(InvocationHandler h):构造函数,用于给内部的h赋值。

static Class getProxyClass (ClassLoaderloader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。

static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)

所谓DynamicProxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然,这个DynamicProxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

在使用动态代理类时,我们必须实现InvocationHandler接口

通过这种方式,被代理的对象(RealSubject)可以在运行时动态改变,需要控制的接口(Subject接口)可以在运行时改变,控制的方式(DynamicSubject类)也可以动态改变,从而实现了非常灵活的动态代理关系。

动态代理步骤
1.创建一个实现接口InvocationHandler的类,它必须实现invoke方法
2.创建被代理的类以及接口
3.通过Proxy的静态方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)创建一个代理
4.通过代理调用方法

三、JDK的动态代理怎么使用?

1、需要动态代理的接口:

[java] view plain copy

  1. package jiankunking;
  2. /**
  3. * 需要动态代理的接口
  4. */
  5. public interface Subject
  6. {
  7. /**
  8. * 你好
  9. *
  10. * @param name
  11. * @return
  12. */
  13. public String SayHello(String name);
  14. /**
  15. * 再见
  16. *
  17. * @return
  18. */
  19. public String SayGoodBye();
  20. }

2、需要代理的实际对象

[java] view plain copy

  1. package jiankunking;
  2. /**
  3. * 实际对象
  4. */
  5. public class RealSubject implements Subject
  6. {
  7. /**
  8. * 你好
  9. *
  10. * @param name
  11. * @return
  12. */
  13. public String SayHello(String name)
  14. {
  15. return "hello " + name;
  16. }
  17. /**
  18. * 再见
  19. *
  20. * @return
  21. */
  22. public String SayGoodBye()
  23. {
  24. return " good bye ";
  25. }
  26. }

3、调用处理器实现类(有木有感觉这里就是传说中的AOP啊)

[java] view plain copy

  1. package jiankunking;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Method;
  4. /**
  5. * 调用处理器实现类
  6. * 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象
  7. */
  8. public class InvocationHandlerImpl implements InvocationHandler
  9. {
  10. /**
  11. * 这个就是我们要代理的真实对象
  12. */
  13. private Object subject;
  14. /**
  15. * 构造方法,给我们要代理的真实对象赋初值
  16. *
  17. * @param subject
  18. */
  19. public InvocationHandlerImpl(Object subject)
  20. {
  21. this.subject = subject;
  22. }
  23. /**
  24. * 该方法负责集中处理动态代理类上的所有方法调用。
  25. * 调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行
  26. *
  27. * @param proxy  代理类实例
  28. * @param method 被调用的方法对象
  29. * @param args   调用参数
  30. * @return
  31. * @throws Throwable
  32. */
  33. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
  34. {
  35. //在代理真实对象前我们可以添加一些自己的操作
  36. System.out.println("在调用之前,我要干点啥呢?");
  37. System.out.println("Method:" + method);
  38. //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
  39. Object returnValue = method.invoke(subject, args);
  40. //在代理真实对象后我们也可以添加一些自己的操作
  41. System.out.println("在调用之后,我要干点啥呢?");
  42. return returnValue;
  43. }
  44. }

4、测试

[java] view plain copy

  1. package jiankunking;
  2. import java.lang.reflect.InvocationHandler;
  3. import java.lang.reflect.Proxy;
  4. /**
  5. * 动态代理演示
  6. */
  7. public class DynamicProxyDemonstration
  8. {
  9. public static void main(String[] args)
  10. {
  11. //代理的真实对象
  12. Subject realSubject = new RealSubject();
  13. /**
  14. * InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
  15. * 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
  16. * 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
  17. */
  18. InvocationHandler handler = new InvocationHandlerImpl(realSubject);
  19. ClassLoader loader = realSubject.getClass().getClassLoader();
  20. Class[] interfaces = realSubject.getClass().getInterfaces();
  21. /**
  22. * 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
  23. */
  24. Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
  25. System.out.println("动态代理对象的类型:"+subject.getClass().getName());
  26. String hello = subject.SayHello("jiankunking");
  27. System.out.println(hello);
  28. //        String goodbye = subject.SayGoodBye();
  29. //        System.out.println(goodbye);
  30. }
  31. }

5、输出结果如下:

演示demo下载地址:http://download.csdn.net/detail/xunzaosiyecao/9597388

四、动态代理怎么实现的?

从使用代码中可以看出,关键点在:

[java] view plain copy

  1. Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);

通过跟踪提示代码可以看出:当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用。

也就是说,当代码执行到:

subject.SayHello("jiankunking")这句话时,会自动调用InvocationHandlerImpl的invoke方法。这是为啥呢?

======================横线之间的是代码跟分析的过程,不想看的朋友可以直接看结论=====================================

以下代码来自:JDK1.8.0_92

既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么?

[java] view plain copy

  1. /**
  2. * Returns an instance of a proxy class for the specified interfaces
  3. * that dispatches method invocations to the specified invocation
  4. * handler.
  5. *
  6. * <p>{@code Proxy.newProxyInstance} throws
  7. * {@code IllegalArgumentException} for the same reasons that
  8. * {@code Proxy.getProxyClass} does.
  9. *
  10. * @param   loader the class loader to define the proxy class
  11. * @param   interfaces the list of interfaces for the proxy class
  12. *          to implement
  13. * @param   h the invocation handler to dispatch method invocations to
  14. * @return  a proxy instance with the specified invocation handler of a
  15. *          proxy class that is defined by the specified class loader
  16. *          and that implements the specified interfaces
  17. * @throws  IllegalArgumentException if any of the restrictions on the
  18. *          parameters that may be passed to {@code getProxyClass}
  19. *          are violated
  20. * @throws  SecurityException if a security manager, <em>s</em>, is present
  21. *          and any of the following conditions is met:
  22. *          <ul>
  23. *          <li> the given {@code loader} is {@code null} and
  24. *               the caller‘s class loader is not {@code null} and the
  25. *               invocation of {@link SecurityManager#checkPermission
  26. *               s.checkPermission} with
  27. *               {@code RuntimePermission("getClassLoader")} permission
  28. *               denies access;</li>
  29. *          <li> for each proxy interface, {@code intf},
  30. *               the caller‘s class loader is not the same as or an
  31. *               ancestor of the class loader for {@code intf} and
  32. *               invocation of {@link SecurityManager#checkPackageAccess
  33. *               s.checkPackageAccess()} denies access to {@code intf};</li>
  34. *          <li> any of the given proxy interfaces is non-public and the
  35. *               caller class is not in the same {@linkplain Package runtime package}
  36. *               as the non-public interface and the invocation of
  37. *               {@link SecurityManager#checkPermission s.checkPermission} with
  38. *               {@code ReflectPermission("newProxyInPackage.{package name}")}
  39. *               permission denies access.</li>
  40. *          </ul>
  41. * @throws  NullPointerException if the {@code interfaces} array
  42. *          argument or any of its elements are {@code null}, or
  43. *          if the invocation handler, {@code h}, is
  44. *          {@code null}
  45. */
  46. @CallerSensitive
  47. public static Object newProxyInstance(ClassLoader loader,
  48. Class<?>[] interfaces,
  49. InvocationHandler h)
  50. throws IllegalArgumentException
  51. {
  52. //检查h 不为空,否则抛异常
  53. Objects.requireNonNull(h);
  54. final Class<?>[] intfs = interfaces.clone();
  55. final SecurityManager sm = System.getSecurityManager();
  56. if (sm != null) {
  57. checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
  58. }
  59. /*
  60. * 获得与指定类装载器和一组接口相关的代理类类型对象
  61. */
  62. Class<?> cl = getProxyClass0(loader, intfs);
  63. /*
  64. * 通过反射获取构造函数对象并生成代理类实例
  65. */
  66. try {
  67. if (sm != null) {
  68. checkNewProxyPermission(Reflection.getCallerClass(), cl);
  69. }
  70. //获取代理对象的构造方法(也就是$Proxy0(InvocationHandler h))
  71. final Constructor<?> cons = cl.getConstructor(constructorParams);
  72. final InvocationHandler ih = h;
  73. if (!Modifier.isPublic(cl.getModifiers())) {
  74. AccessController.doPrivileged(new PrivilegedAction<Void>() {
  75. public Void run() {
  76. cons.setAccessible(true);
  77. return null;
  78. }
  79. });
  80. }
  81. //生成代理类的实例并把InvocationHandlerImpl的实例传给它的构造方法
  82. return cons.newInstance(new Object[]{h});
  83. } catch (IllegalAccessException|InstantiationException e) {
  84. throw new InternalError(e.toString(), e);
  85. } catch (InvocationTargetException e) {
  86. Throwable t = e.getCause();
  87. if (t instanceof RuntimeException) {
  88. throw (RuntimeException) t;
  89. } else {
  90. throw new InternalError(t.toString(), t);
  91. }
  92. } catch (NoSuchMethodException e) {
  93. throw new InternalError(e.toString(), e);
  94. }
  95. }

我们再进去getProxyClass0方法看一下:

[java] view plain copy

  1. /**
  2. * Generate a proxy class.  Must call the checkProxyAccess method
  3. * to perform permission checks before calling this.
  4. */
  5. private static Class<?> getProxyClass0(ClassLoader loader,
  6. Class<?>... interfaces) {
  7. if (interfaces.length > 65535) {
  8. throw new IllegalArgumentException("interface limit exceeded");
  9. }
  10. // If the proxy class defined by the given loader implementing
  11. // the given interfaces exists, this will simply return the cached copy;
  12. // otherwise, it will create the proxy class via the ProxyClassFactory
  13. return proxyClassCache.get(loader, interfaces);
  14. }

真相还是没有来到,继续,看一下proxyClassCache

[java] view plain copy

  1. /**
  2. * a cache of proxy classes
  3. */
  4. private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
  5. proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

奥,原来用了一下缓存啊

那么它对应的get方法啥样呢?

[java] view plain copy

  1. /**
  2. * Look-up the value through the cache. This always evaluates the
  3. * {@code subKeyFactory} function and optionally evaluates
  4. * {@code valueFactory} function if there is no entry in the cache for given
  5. * pair of (key, subKey) or the entry has already been cleared.
  6. *
  7. * @param key       possibly null key
  8. * @param parameter parameter used together with key to create sub-key and
  9. *                  value (should not be null)
  10. * @return the cached value (never null)
  11. * @throws NullPointerException if {@code parameter} passed in or
  12. *                              {@code sub-key} calculated by
  13. *                              {@code subKeyFactory} or {@code value}
  14. *                              calculated by {@code valueFactory} is null.
  15. */
  16. public V get(K key, P parameter) {
  17. Objects.requireNonNull(parameter);
  18. expungeStaleEntries();
  19. Object cacheKey = CacheKey.valueOf(key, refQueue);
  20. // lazily install the 2nd level valuesMap for the particular cacheKey
  21. ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
  22. if (valuesMap == null) {
  23. //putIfAbsent这个方法在key不存在的时候加入一个值,如果key存在就不放入
  24. ConcurrentMap<Object, Supplier<V>> oldValuesMap
  25. = map.putIfAbsent(cacheKey,
  26. valuesMap = new ConcurrentHashMap<>());
  27. if (oldValuesMap != null) {
  28. valuesMap = oldValuesMap;
  29. }
  30. }
  31. // create subKey and retrieve the possible Supplier<V> stored by that
  32. // subKey from valuesMap
  33. Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
  34. Supplier<V> supplier = valuesMap.get(subKey);
  35. Factory factory = null;
  36. while (true) {
  37. if (supplier != null) {
  38. // supplier might be a Factory or a CacheValue<V> instance
  39. V value = supplier.get();
  40. if (value != null) {
  41. return value;
  42. }
  43. }
  44. // else no supplier in cache
  45. // or a supplier that returned null (could be a cleared CacheValue
  46. // or a Factory that wasn‘t successful in installing the CacheValue)
  47. // lazily construct a Factory
  48. if (factory == null) {
  49. factory = new Factory(key, parameter, subKey, valuesMap);
  50. }
  51. if (supplier == null) {
  52. supplier = valuesMap.putIfAbsent(subKey, factory);
  53. if (supplier == null) {
  54. // successfully installed Factory
  55. supplier = factory;
  56. }
  57. // else retry with winning supplier
  58. } else {
  59. if (valuesMap.replace(subKey, supplier, factory)) {
  60. // successfully replaced
  61. // cleared CacheEntry / unsuccessful Factory
  62. // with our Factory
  63. supplier = factory;
  64. } else {
  65. // retry with current supplier
  66. supplier = valuesMap.get(subKey);
  67. }
  68. }
  69. }
  70. }

我们可以看到它调用了 supplier.get(); 获取动态代理类,其中supplier是Factory,这个类定义在WeakCach的内部。

来瞅瞅,get里面又做了什么?

[java] view plain copy

  1. public synchronized V get() { // serialize access
  2. // re-check
  3. Supplier<V> supplier = valuesMap.get(subKey);
  4. if (supplier != this) {
  5. // something changed while we were waiting:
  6. // might be that we were replaced by a CacheValue
  7. // or were removed because of failure ->
  8. // return null to signal WeakCache.get() to retry
  9. // the loop
  10. return null;
  11. }
  12. // else still us (supplier == this)
  13. // create new value
  14. V value = null;
  15. try {
  16. value = Objects.requireNonNull(valueFactory.apply(key, parameter));
  17. } finally {
  18. if (value == null) { // remove us on failure
  19. valuesMap.remove(subKey, this);
  20. }
  21. }
  22. // the only path to reach here is with non-null value
  23. assert value != null;
  24. // wrap value with CacheValue (WeakReference)
  25. CacheValue<V> cacheValue = new CacheValue<>(value);
  26. // try replacing us with CacheValue (this should always succeed)
  27. if (valuesMap.replace(subKey, this, cacheValue)) {
  28. // put also in reverseMap
  29. reverseMap.put(cacheValue, Boolean.TRUE);
  30. } else {
  31. throw new AssertionError("Should not reach here");
  32. }
  33. // successfully replaced us with new CacheValue -> return the value
  34. // wrapped by it
  35. return value;
  36. }
  37. }

发现重点还是木有出现,但我们可以看到它调用了valueFactory.apply(key, parameter)方法:

[java] view plain copy

  1. /**
  2. * A factory function that generates, defines and returns the proxy class given
  3. * the ClassLoader and array of interfaces.
  4. */
  5. private static final class ProxyClassFactory
  6. implements BiFunction<ClassLoader, Class<?>[], Class<?>>
  7. {
  8. // prefix for all proxy class names
  9. private static final String proxyClassNamePrefix = "$Proxy";
  10. // next number to use for generation of unique proxy class names
  11. private static final AtomicLong nextUniqueNumber = new AtomicLong();
  12. @Override
  13. public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
  14. Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
  15. for (Class<?> intf : interfaces) {
  16. /*
  17. * Verify that the class loader resolves the name of this
  18. * interface to the same Class object.
  19. */
  20. Class<?> interfaceClass = null;
  21. try {
  22. interfaceClass = Class.forName(intf.getName(), false, loader);
  23. } catch (ClassNotFoundException e) {
  24. }
  25. if (interfaceClass != intf) {
  26. throw new IllegalArgumentException(
  27. intf + " is not visible from class loader");
  28. }
  29. /*
  30. * Verify that the Class object actually represents an
  31. * interface.
  32. */
  33. if (!interfaceClass.isInterface()) {
  34. throw new IllegalArgumentException(
  35. interfaceClass.getName() + " is not an interface");
  36. }
  37. /*
  38. * Verify that this interface is not a duplicate.
  39. */
  40. if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
  41. throw new IllegalArgumentException(
  42. "repeated interface: " + interfaceClass.getName());
  43. }
  44. }
  45. String proxyPkg = null;     // package to define proxy class in
  46. int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
  47. /*
  48. * Record the package of a non-public proxy interface so that the
  49. * proxy class will be defined in the same package.  Verify that
  50. * all non-public proxy interfaces are in the same package.
  51. */
  52. for (Class<?> intf : interfaces) {
  53. int flags = intf.getModifiers();
  54. if (!Modifier.isPublic(flags)) {
  55. accessFlags = Modifier.FINAL;
  56. String name = intf.getName();
  57. int n = name.lastIndexOf(‘.‘);
  58. String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
  59. if (proxyPkg == null) {
  60. proxyPkg = pkg;
  61. } else if (!pkg.equals(proxyPkg)) {
  62. throw new IllegalArgumentException(
  63. "non-public interfaces from different packages");
  64. }
  65. }
  66. }
  67. if (proxyPkg == null) {
  68. // if no non-public proxy interfaces, use com.sun.proxy package
  69. proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
  70. }
  71. /*
  72. * Choose a name for the proxy class to generate.
  73. */
  74. long num = nextUniqueNumber.getAndIncrement();
  75. String proxyName = proxyPkg + proxyClassNamePrefix + num;
  76. /*
  77. * Generate the specified proxy class.
  78. */
  79. byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
  80. proxyName, interfaces, accessFlags);
  81. try {
  82. return defineClass0(loader, proxyName,
  83. proxyClassFile, 0, proxyClassFile.length);
  84. } catch (ClassFormatError e) {
  85. /*
  86. * A ClassFormatError here means that (barring bugs in the
  87. * proxy class generation code) there was some other
  88. * invalid aspect of the arguments supplied to the proxy
  89. * class creation (such as virtual machine limitations
  90. * exceeded).
  91. */
  92. throw new IllegalArgumentException(e.toString());
  93. }
  94. }
  95. }

通过看代码终于找到了重点:

[java] view plain copy

  1. //生成字节码
  2. byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);

那么接下来我们也使用测试一下,使用这个方法生成的字节码是个什么样子:

[java] view plain copy

  1. package jiankunking;
  2. import sun.misc.ProxyGenerator;
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.lang.reflect.InvocationHandler;
  8. import java.lang.reflect.Proxy;
  9. /**
  10. * 动态代理演示
  11. */
  12. public class DynamicProxyDemonstration
  13. {
  14. public static void main(String[] args)
  15. {
  16. //代理的真实对象
  17. Subject realSubject = new RealSubject();
  18. /**
  19. * InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
  20. * 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
  21. * 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
  22. */
  23. InvocationHandler handler = new InvocationHandlerImpl(realSubject);
  24. ClassLoader loader = handler.getClass().getClassLoader();
  25. Class[] interfaces = realSubject.getClass().getInterfaces();
  26. /**
  27. * 该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
  28. */
  29. Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);
  30. System.out.println("动态代理对象的类型:"+subject.getClass().getName());
  31. String hello = subject.SayHello("jiankunking");
  32. System.out.println(hello);
  33. // 将生成的字节码保存到本地,
  34. createProxyClassFile();
  35. }
  36. private static void createProxyClassFile(){
  37. String name = "ProxySubject";
  38. byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{Subject.class});
  39. FileOutputStream out =null;
  40. try {
  41. out = new FileOutputStream(name+".class");
  42. System.out.println((new File("hello")).getAbsolutePath());
  43. out.write(data);
  44. } catch (FileNotFoundException e) {
  45. e.printStackTrace();
  46. } catch (IOException e) {
  47. e.printStackTrace();
  48. }finally {
  49. if(null!=out) try {
  50. out.close();
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. }
  56. }

可以看一下这里代理对象的类型:

我们用jd-jui 工具将生成的字节码反编译:

[java] view plain copy

  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. import java.lang.reflect.UndeclaredThrowableException;
  5. import jiankunking.Subject;
  6. public final class ProxySubject
  7. extends Proxy
  8. implements Subject
  9. {
  10. private static Method m1;
  11. private static Method m3;
  12. private static Method m4;
  13. private static Method m2;
  14. private static Method m0;
  15. public ProxySubject(InvocationHandler paramInvocationHandler)
  16. {
  17. super(paramInvocationHandler);
  18. }
  19. public final boolean equals(Object paramObject)
  20. {
  21. try
  22. {
  23. return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
  24. }
  25. catch (Error|RuntimeException localError)
  26. {
  27. throw localError;
  28. }
  29. catch (Throwable localThrowable)
  30. {
  31. throw new UndeclaredThrowableException(localThrowable);
  32. }
  33. }
  34. public final String SayGoodBye()
  35. {
  36. try
  37. {
  38. return (String)this.h.invoke(this, m3, null);
  39. }
  40. catch (Error|RuntimeException localError)
  41. {
  42. throw localError;
  43. }
  44. catch (Throwable localThrowable)
  45. {
  46. throw new UndeclaredThrowableException(localThrowable);
  47. }
  48. }
  49. public final String SayHello(String paramString)
  50. {
  51. try
  52. {
  53. return (String)this.h.invoke(this, m4, new Object[] { paramString });
  54. }
  55. catch (Error|RuntimeException localError)
  56. {
  57. throw localError;
  58. }
  59. catch (Throwable localThrowable)
  60. {
  61. throw new UndeclaredThrowableException(localThrowable);
  62. }
  63. }
  64. public final String toString()
  65. {
  66. try
  67. {
  68. return (String)this.h.invoke(this, m2, null);
  69. }
  70. catch (Error|RuntimeException localError)
  71. {
  72. throw localError;
  73. }
  74. catch (Throwable localThrowable)
  75. {
  76. throw new UndeclaredThrowableException(localThrowable);
  77. }
  78. }
  79. public final int hashCode()
  80. {
  81. try
  82. {
  83. return ((Integer)this.h.invoke(this, m0, null)).intValue();
  84. }
  85. catch (Error|RuntimeException localError)
  86. {
  87. throw localError;
  88. }
  89. catch (Throwable localThrowable)
  90. {
  91. throw new UndeclaredThrowableException(localThrowable);
  92. }
  93. }
  94. static
  95. {
  96. try
  97. {
  98. m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
  99. m3 = Class.forName("jiankunking.Subject").getMethod("SayGoodBye", new Class[0]);
  100. m4 = Class.forName("jiankunking.Subject").getMethod("SayHello", new Class[] { Class.forName("java.lang.String") });
  101. m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
  102. m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
  103. return;
  104. }
  105. catch (NoSuchMethodException localNoSuchMethodException)
  106. {
  107. throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
  108. }
  109. catch (ClassNotFoundException localClassNotFoundException)
  110. {
  111. throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
  112. }
  113. }
  114. }

这就是最终真正的代理类,它继承自Proxy并实现了我们定义的Subject接口
也就是说:

[java] view plain copy

  1. Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);

这里的subject实际是这个类的一个实例,那么我们调用它的:

[java] view plain copy

  1. public final String SayHello(String paramString)

就是调用我们定义的InvocationHandlerImpl的 invoke方法:

======================横线之间的是代码跟分析的过程,不想看的朋友可以直接看结论=====================================

五、结论

到了这里,终于解答了:
subject.SayHello("jiankunking")这句话时,为什么会自动调用InvocationHandlerImpl的invoke方法?

因为JDK生成的最终真正的代理类,它继承自Proxy并实现了我们定义的Subject接口,在实现Subject接口方法的内部,通过反射调用了
InvocationHandlerImpl的invoke方法。

包含生成本地class文件的demo:http://download.csdn.net/detail/xunzaosiyecao/9597474
通过分析代码可以看出Java 动态代理,具体有如下四步骤:
  1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
  2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
  3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
  4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
时间: 2024-10-06 07:42:39

【转载】Java JDK 动态代理(AOP)使用及实现原理分析的相关文章

Java JDK动态代理

通过JS操作DOM节点可能以节点为单位进行,比如添加节点,可以createElement,createTextNode,然后用appendChild把文本节点和容器节点绑定在一起,然后再用appendChild或insertBefor添加到DOM树中.但如果要往DOM树中动态添加大量的节点.就会很麻烦.而且每次都会刷新DOM,造成性能上的缺陷. 解决方法是使用文档碎片这个方法创建文档碎片. 我个人觉得应该把这个翻译成文档片段比较合适. 使用jQuery解决方案. <span style="

[转载] java的动态代理机制详解

转载自http://www.cnblogs.com/xiaoluo501395377/p/3383130.html 代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理

java JDK动态代理的机制

一:前言 自己在稳固spring的一些特性的时候在网上看到了遮掩的一句话“利用接口的方式,spring aop将默认通过JDK的动态代理来实现代理类,不适用接口时spring aop将使用通过cglib 来实现代理类",我对JDK的动态代理机制其实一点都不了解,学习java的时候也是只是知道会用,会去查api的文档就行,所以这些底层的操作方式我自己不是很清楚,现在既然要了解一些底层的代码,就谢谢自己的想发,大部分都是差不多的. 二:实现 先给出接口和实现类的代码: UserDao.java: p

Java 8 动态类型语言Lambda表达式实现原理分析

Java 8支持动态语言,看到了很酷的Lambda表达式,对一直以静态类型语言自居的Java,让人看到了Java虚拟机可以支持动态语言的目标. import java.util.function.Consumer; public class Lambda { public static void main(String[] args) { Consumer<String> c = s -> System.out.println(s); c.accept("hello lambd

【原创】JDK动态代理,此次之后,永生难忘。

动态代理,这个词在Java的世界里面经常被提起,尤其是对于部分(这里强调“部分”二字,因为有做了一两年就成大神的,实力强的令人发指,这类人无疑是非常懂动态代理这点小伎俩的)做了一两年新人来说,总是摸不清楚来龙去脉,一两年是个坎,为什么是一两年,才入门的新人可能对这东西没什么感觉,没到这一步,做了很久开发的人显然是明白这其中原理的,而做了一两年的,知其然而不知其所以然,所以一两年工作经验的人很多是很茫然的. 那么,这里就相对比较比较深入一点的介绍JDK动态代理的原理.这样子介绍完,明白了其中的道理

JDK动态代理,接口代理

在了解jdk代理之前,我们要知道什么是动态代理?动态代理可以干什么呢? 在现实生活中有很多代理对象(如明星代理),可以实现真实对象的功能,还在真实对象的基础上添加了新的功能,保证真实对象没有被修改.而jdk动态代理就和这个实现原理大概一致. 简介: 需要存在抽象对象,定义所有的功能 真实对象实现抽象对象所有的功能 通过Proxy类,创建代理对象,调用代理方法 在InvocationHandler的invoke对代理的方法有选择的修改或不修改真实对象原有的方法. 抽象角色 package com.

Java代理之(jdk静态代理/jdk动态代理/cglib动态代理/aop/aspectj)

一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法.如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱.所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户.而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品. 专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象

Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

一.概念 代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道.如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法.如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱.所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户.而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品. 专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象

【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理

原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码通过横向切割的方式抽取到一个独立的模块中. 一.AOP术语 1.连接点(Joinpoint) 程序执行的某个特定位置:如类开始初始化之前.类初始化之后.类某个方法调用前.调用后等:一个类