一、什么是代理?

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

代理模式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方法:
======================横线之间的是代码跟分析的过程,不想看的朋友可以直接看结论=====================================

五、结论

到了这里,终于解答了:  转http://blog.csdn.net/jiankunking/article/details/52143504
subject.SayHello("jiankunking")这句话时,为什么会自动调用InvocationHandlerImpl的invoke方法?

因为JDK生成的最终真正的代理类,它继承自Proxy并实现了我们定义的Subject接口,在实现Subject接口方法的内部,通过反射调用了
InvocationHandlerImpl的invoke方法。
通过分析代码可以看出Java 动态代理,具体有如下四步骤:
  1. 通过实现 InvocationHandler 接口创建自己的调用处理器;
  2. 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
  3. 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
  4. 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

java动态代理_aop2的更多相关文章

  1. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  2. Java动态代理全面分析

    代理模式 解说:给某一个对象提供一个代理,并由代理对象控制对原对象的引用: 代理模式需要以下几个角色: 1  主题:规定代理类和真实对象共同对外暴露的接口: 2  代理类:专门代理真实对象的类: 3 ...

  3. JAVA动态代理模式(从现实生活角度理解代码原理)

    所谓动态代理,即通过代理类:Proxy的代理,接口和实现类之间可以不直接发生联系,而可以在运行期(Runtime)实现动态关联. java动态代理主要是使用java.lang.reflect包中的两个 ...

  4. Java 动态代理作用是什么?

    Java 动态代理作用是什么?   1 条评论 分享   默认排序按时间排序 19 个回答 133赞同反对,不会显示你的姓名 Intopass 程序员,近期沉迷于动漫ING 133 人赞同 ① 首先你 ...

  5. java动态代理原理

    我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...

  6. java 动态代理示例,带主要注释

    Java proxy是基于反射,仅仅支持基于接口的动态代理. java 动态代理是一切架构的基础,必须了解. 废话少说,先上代码获得感性认识. 示例代码有主要注释. 接口: public interf ...

  7. java动态代理浅析

    最近在公司看到了mybatis与spring整合中MapperScannerConfigurer的使用,该类通过反向代理自动生成基于接口的动态代理类. 于是想起了java的动态代理,然后就有了这篇文章 ...

  8. Java 动态代理

    被代理的接口特点: 1. 不能有重复的接口,以避免动态代理类代码生成时的编译错误. 2. 这些接口对于类装载器必须可见,否则类装载器将无法链接它们,将会导致类定义失败. 3. 需被代理的所有非 pub ...

  9. [转]java动态代理(JDK和cglib)

    转自:http://www.cnblogs.com/jqyp/archive/2010/08/20/1805041.html java动态代理(JDK和cglib) JAVA的动态代理 代理模式 代理 ...

随机推荐

  1. T4:使用 T4 消除程序和配置文件中重复的字符串信息

    背景 我们经常在配置文件中配置各种:id.name,然后在程序中使用这些配置获取信息,这导致了字符串重复出现在系统的多个地方,非常不利于维护,本文介绍采用 T4 来消除这种重复. T4 消除重复 配置 ...

  2. C#零基础入门03:打老鼠初级

    一:在源码管理器中打开VS 注意,下文这样的打开方式是在 TFS 的源码服务器中打开解决方案.如果我们使用 SVN,则直接在硬盘上打开解决方案就可以了. 打开VS: 然后按上图中的步骤1和2(双击2处 ...

  3. 说说初用 Mock 工具测试碰到的坑

    我是一个在校实习生,作为一个程序猿,是个菜鸟中战斗机!对于测试,只写过一点点简单到不能再简单了的 Junit 单元测试的例子(因为当时这足以应付学校课程的内容与要求).这几天在公司里要真枪实弹做测试的 ...

  4. jcseg-1.8.7版本发布 - 多配置适应+完整开发帮助文档

    jcseg是使用java开发的一款开源中文分词器, 并且提供了最新版本的lucene和solr分词接口. jcseg 1.8.7版本发布了: 1. 更改了内部设计, 加入JcsegTaskConfig ...

  5. iOS:三种常见计时器(NSTimer、CADisplayLink、dispatch_source_t)的使用

    一.介绍 在iOS中,计时器是比较常用的,用于统计累加数据或者倒计时等,例如手机号获取验证码.计时器大概有那么三种,分别是:NSTimer.CADisplayLink.dispatch_source_ ...

  6. 奇怪吸引子---DequanLi

    奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...

  7. scrapy框架系列 (2) 一个简单案例

    学习目标 创建一个Scrapy项目 定义提取的结构化数据(Item) 编写爬取网站的 Spider 并提取出结构化数据(Item) 编写 Item Pipelines 来存储提取到的Item(即结构化 ...

  8. VS2010 SP1安装失败之”此计算机的状态不支持此安装“()

    升级安装VS2010SP1的时候,出现“此计算机的状态不支持此安装”,Google得之: 如下图显示: 安装程序已经检测到,此计算机不满足安装此软件所需的条件.必须先解决以下这些造成阻止的问题,才可以 ...

  9. Search Insert Position leetcode java

    Given a sorted array and a target value, return the index if the target is found. If not, return the ...

  10. 对象引用 方法传参 值传递 引用传递 易错点 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...