1.接口类

  1. public interface UserService {
  2. JSONObject getUser();
  3. }

接口实现类

  1. public class UserServiceImpl implements UserService {
  2. @Override
  3. public JSONObject getUser() {
  4. JSONObject object = new JSONObject();
  5. object.put("name", "meikb");
  6. return object;
  7. }
  8. }

3.1代理类

使用代理类来 传递要代理的对象,这个对象可以是任何对象,所有可以是obj, 也可传入类.

3.1.1 object

  1. public class ProxyHandler implements InvocationHandler {
  2. private Object object; //定义obj对象可以支持任何对象传入
  3. public ProxyHandler(Object object){
  4. this.object = object;
  5. }
  6. @Override
  7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  8. System.out.println(method.getName() + "方法被调用");
  9. Object result = method.invoke(object, args);
  10. System.out.println(method.getName() + "调用完成");
  11. return result;
  12. }
  13. public Object getJDKProxy(Object object){
  14. return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
  15. }
  16. }

3.1.2 class

  1. public class ProxyHandler implements InvocationHandler {
  2. private Class clazz; //传入class参数
  3. @Override
  4. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  5. System.out.println(method.getName() + "方法被调用");
  6. Object result = method.invoke(clazz.newInstance(), args);
  7. System.out.println( "结果" + result.toString());
  8. System.out.println(method.getName() + "调用完成");
  9. return result;
  10. }
  11. public <T>T getJDKProxy(Class clazz){
  12. this.clazz = clazz;
  13. return (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
  14. }
  15. }

4.使用方式

1.对象传入调用方式

  1. public class ProxyMain {
  2. public static void main(String[] args) {
  3. UserService userService = new UserServiceImpl();
  4. ProxyHandler handler = new ProxyHandler(userService);
  5. UserService userProxy = (UserService)handler.getJDKProxy(userService);
  6. System.out.println(userProxy.getUser().toJSONString());
  7. }
  8. }

2.class传入调用方式

  1. public class UserMain {
  2. public static void main(String[] args) {
  3. ProxyHandler handler = new ProxyHandler();
  4. UserService userService = handler.getJDKProxy(UserServiceImpl.class);
  5. userService.getUser();
  6. }
  7. }

5.实现原理

image.png
1.当调用Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); 这行代码的是 进入

  1. public static Object newProxyInstance(ClassLoader loader,
  2. Class<?>[] interfaces,
  3. InvocationHandler h)
  4. throws IllegalArgumentException
  5. {
  6. Objects.requireNonNull(h);
  7. final Class<?>[] intfs = interfaces.clone();
  8. final SecurityManager sm = System.getSecurityManager();
  9. if (sm != null) {
  10. checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
  11. }
  12. /*
  13. * Look up or generate the designated proxy class.
  14. */
  15. Class<?> cl = getProxyClass0(loader, intfs);
  16. /*
  17. * Invoke its constructor with the designated invocation handler.
  18. */
  19. try {
  20. if (sm != null) {
  21. checkNewProxyPermission(Reflection.getCallerClass(), cl);
  22. }
  23. final Constructor<?> cons = cl.getConstructor(constructorParams);
  24. final InvocationHandler ih = h;
  25. if (!Modifier.isPublic(cl.getModifiers())) {
  26. AccessController.doPrivileged(new PrivilegedAction<Void>() {
  27. public Void run() {
  28. cons.setAccessible(true);
  29. return null;
  30. }
  31. });
  32. }
  33. return cons.newInstance(new Object[]{h});
  34. } catch (IllegalAccessException|InstantiationException e) {
  35. throw new InternalError(e.toString(), e);
  36. } catch (InvocationTargetException e) {
  37. Throwable t = e.getCause();
  38. if (t instanceof RuntimeException) {
  39. throw (RuntimeException) t;
  40. } else {
  41. throw new InternalError(t.toString(), t);
  42. }
  43. } catch (NoSuchMethodException e) {
  44. throw new InternalError(e.toString(), e);
  45. }
  46. }

里面有一个方法是 getProxyClass0 就是获取代理类,获取代理类通过发射就可以获取代理对象。getProxyClass0 内部

  1. private static Class<?> getProxyClass0(ClassLoader loader,
  2. Class<?>... interfaces) {
  3. if (interfaces.length > 65535) {
  4. throw new IllegalArgumentException("interface limit exceeded");
  5. }
  6. // If the proxy class defined by the given loader implementing
  7. // the given interfaces exists, this will simply return the cached copy;
  8. // otherwise, it will create the proxy class via the ProxyClassFactory
  9. return proxyClassCache.get(loader, interfaces);
  10. }

直接调用proxyClassCache.get 可以看到生成代理类的时候 是存在缓存的 ,提高效率

  1. public V get(K key, P parameter) {
  2. Objects.requireNonNull(parameter);
  3. expungeStaleEntries();
  4. Object cacheKey = CacheKey.valueOf(key, refQueue);
  5. // lazily install the 2nd level valuesMap for the particular cacheKey
  6. ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
  7. if (valuesMap == null) {
  8. ConcurrentMap<Object, Supplier<V>> oldValuesMap
  9. = map.putIfAbsent(cacheKey,
  10. valuesMap = new ConcurrentHashMap<>());
  11. if (oldValuesMap != null) {
  12. valuesMap = oldValuesMap;
  13. }
  14. }
  15. // create subKey and retrieve the possible Supplier<V> stored by that
  16. // subKey from valuesMap
  17. Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
  18. Supplier<V> supplier = valuesMap.get(subKey);
  19. Factory factory = null;
  20. while (true) {
  21. ......
  22. }
  23. }

上面是通过 subKeyFactory.apply(key, parameter) 这个在返回到Proxy 内部调用内部类

  1. public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
  2. ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
  3. final byte[] var4 = var3.generateClassFile();
  4. if (saveGeneratedFiles) {
  5. ......
  6. }
  7. return var4;
  8. }
  9. private byte[] generateClassFile() {
  10. this.addProxyMethod(hashCodeMethod, Object.class);
  11. this.addProxyMethod(equalsMethod, Object.class);
  12. this.addProxyMethod(toStringMethod, Object.class);
  13. Class[] var1 = this.interfaces;
  14. int var2 = var1.length;
  15. int var3;
  16. Class var4;
  17. for(var3 = 0; var3 < var2; ++var3) {
  18. var4 = var1[var3];
  19. Method[] var5 = var4.getMethods();
  20. int var6 = var5.length;
  21. for(int var7 = 0; var7 < var6; ++var7) {
  22. Method var8 = var5[var7];
  23. this.addProxyMethod(var8, var4);
  24. }
  25. }
  26. ......
  27. }

可以看到是通过io 把新生成的代码写到文件中,然后通过反编译生成class文件。