content: package com.alibaba.asyncload.impl;
  
  import java.lang.reflect.Method;
  import java.lang.reflect.Modifier;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import java.util.concurrent.Future;
  
  import net.sf.cglib.proxy.Callback;
  import net.sf.cglib.proxy.CallbackFilter;
  import net.sf.cglib.proxy.Dispatcher;
  import net.sf.cglib.proxy.Enhancer;
  import net.sf.cglib.proxy.MethodInterceptor;
  import net.sf.cglib.proxy.MethodProxy;
  
  import com.alibaba.asyncload.AsyncLoadConfig;
  import com.alibaba.asyncload.AsyncLoadExecutor;
  import com.alibaba.asyncload.AsyncLoadMethodMatch;
  import com.alibaba.asyncload.AsyncLoadProxy;
  import com.alibaba.asyncload.impl.exceptions.AsyncLoadException;
  import com.alibaba.asyncload.impl.helper.AsyncLoadProxyRepository;
  import com.alibaba.asyncload.impl.helper.AsyncLoadReflectionHelper;
  import com.alibaba.asyncload.impl.pool.AsyncLoadCallable;
  import com.alibaba.asyncload.impl.util.AsyncLoadBarrier;
  import com.alibaba.asyncload.impl.util.AsyncLoadUtils;
  
  /**
   * 基于cglib enhance proxy的实现
   * 
   * <pre>
   * 参数说明：
   * 1. targetClass : 用于明确cglib生成的目标对象类型。比如一般的service都有一个接口，但serviceImpl有时已经被进行一次cglib代理，生成了final对象，这里可以指定targetClass为其接口对象
   * </pre>
   * 
   * @author jianghang 2011-1-21 下午10:56:39
   */
  public class AsyncLoadEnhanceProxy<T> implements AsyncLoadProxy<T> {
  
      private T                 service;
      private AsyncLoadConfig   config;
      private AsyncLoadExecutor executor;
      private Class<T>          targetClass;
  
      public AsyncLoadEnhanceProxy(){
      }
  
      public AsyncLoadEnhanceProxy(T service, AsyncLoadExecutor executor){
          this(service, new AsyncLoadConfig(), executor);
      }
  
      public AsyncLoadEnhanceProxy(T service, AsyncLoadConfig config, AsyncLoadExecutor executor){
          this.service = service;
          this.config = config;
          this.executor = executor;
          this.targetClass = (Class<T>) service.getClass();// 默认的代理class对象即为service
      }
  
      public T getProxy() {
          validate();
          return getProxyInternal();
      }
  
      /**
       * 相应的检查方法
       */
      private void validate() {
          AsyncLoadUtils.notNull(service, "service should not be null");
          AsyncLoadUtils.notNull(config, "config should not be null");
          AsyncLoadUtils.notNull(executor, "executor should not be null");
  
          if (Modifier.isFinal(targetClass.getModifiers())) { // 目前暂不支持final类型的处理，以后可以考虑使用jdk
                                                              // proxy
              throw new AsyncLoadException("Enhance proxy not support final class :" + targetClass.getName());
          }
  
          if (!Modifier.isPublic(targetClass.getModifiers())) {
              // 处理如果是非public属性，则不进行代理，强制访问会出现IllegalAccessException，比如一些内部类或者匿名类不允许直接访问
              throw new AsyncLoadException("Enhance proxy not support private/protected class :" + targetClass.getName());
          }
      }
  
      class AsyncLoadCallbackFilter implements CallbackFilter {
  
          public int accept(Method method) {
              // 预先进行匹配，直接计算好需要处理的method，避免动态匹配浪费性能
              if (AsyncLoadObject.class.isAssignableFrom(method.getDeclaringClass())) {// 判断对应的方法是否属于AsyncLoadObject
                  return 0; // for AsyncLoadServiceInterceptor
              } else {
                  Map<AsyncLoadMethodMatch, Long> matches = config.getMatches();
                  Set<AsyncLoadMethodMatch> methodMatchs = matches.keySet();
                  if (methodMatchs != null && !methodMatchs.isEmpty()) {
                      for (Iterator<AsyncLoadMethodMatch> methodMatch = methodMatchs.iterator(); methodMatch.hasNext();) {
                          if (methodMatch.next().matches(method)) {
                              return 2; // for AsyncLoadInterceptor
                          }
                      }
                  }
                  return 1; // for AsyncLoadDirect
              }
          }
      }
  
      class AsyncLoadServiceInterceptor implements MethodInterceptor {
  
          public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
              if ("_getOriginalClass".equals(method.getName())) {
                  return getOriginalClass();
              }
              throw new AsyncLoadException("method[" + method.getName() + "] is not support!");
          }
  
          private Object getOriginalClass() {
              return targetClass;
          }
      }
  
      class AsyncLoadDirect implements Dispatcher {
  
          public Object loadObject() throws Exception {
              return service;
          }
  
      }
  
      class AsyncLoadInterceptor implements MethodInterceptor {
  
          public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
              Long timeout = getMatchTimeout(method);
              final Object finObj = service;
              final Object[] finArgs = args;
              final Method finMethod = method;
  
              Class returnClass = method.getReturnType();
              if (Void.TYPE.isAssignableFrom(returnClass)) {// 判断返回值是否为void
                  // 不处理void的函数调用
                  return finMethod.invoke(finObj, finArgs);
              } else if (!Modifier.isPublic(returnClass.getModifiers())) {
                  // 处理如果是非public属性，则不进行代理，强制访问会出现IllegalAccessException，比如一些内部类或者匿名类不允许直接访问
                  return finMethod.invoke(finObj, finArgs);
              } else if (Modifier.isFinal(returnClass.getModifiers())) {
                  // 处理特殊的final类型，目前暂不支持，后续可采用jdk proxy
                  return finMethod.invoke(finObj, finArgs);
              } else if (returnClass.isPrimitive() || returnClass.isArray()) {
                  // 不处理特殊类型，因为无法使用cglib代理
                  return finMethod.invoke(finObj, finArgs);
              } else if (returnClass == Object.class) {
                  // 针对返回对象是Object类型，不做代理。没有具体的method，代理没任何意义
                  return finMethod.invoke(finObj, finArgs);
              } else {
                  Future future = executor.submit(new AsyncLoadCallable() {
  
                      public Object call() throws Exception {
                          try {
                              return finMethod.invoke(finObj, finArgs);// 需要直接委托对应的finObj(service)进行处理
                          } catch (Throwable e) {
                              throw new AsyncLoadException("future invoke error!", e);
                          }
                      }
  
                      public AsyncLoadConfig getConfig() {
                          return config;
                      }
                  });
                  // 够造一个返回的AsyncLoadResult
                  AsyncLoadResult result = new AsyncLoadResult(returnClass, future, timeout);
                  // 继续返回一个代理对象
                  AsyncLoadObject asyncProxy = (AsyncLoadObject) result.getProxy();
                  // 添加到barrier中
                  if (config.getNeedBarrierSupport()) {
                      AsyncLoadBarrier.addTask((AsyncLoadObject) asyncProxy);
                  }
                  // 返回对象
                  return asyncProxy;
              }
  
          }
  
          /**
           * 返回对应的匹配的timeout时间，一定能找到对应的匹配点
           * 
           * @param method
           * @return
           */
          private Long getMatchTimeout(Method method) {
              Map<AsyncLoadMethodMatch, Long> matches = config.getMatches();
              Set<Map.Entry<AsyncLoadMethodMatch, Long>> entrys = matches.entrySet();
              if (entrys != null && !entrys.isEmpty()) {
                  for (Iterator<Map.Entry<AsyncLoadMethodMatch, Long>> iter = entrys.iterator(); iter.hasNext();) {
                      Map.Entry<AsyncLoadMethodMatch, Long> entry = iter.next();
                      if (entry.getKey().matches(method)) {
                          return entry.getValue();
                      }
                  }
              }
  
              return config.getDefaultTimeout();
          }
      }
  
      // =========================== help mehotd =================================
  
      /**
       * 优先从Repository进行获取ProxyClass,创建对应的object
       * 
       * @return
       */
      private T getProxyInternal() {
          Class proxyClass = AsyncLoadProxyRepository.getProxy(targetClass.getName());
          if (proxyClass == null) {
              Enhancer enhancer = new Enhancer();
              if (targetClass.isInterface()) { // 判断是否为接口，优先进行接口代理可以解决service为final
                  enhancer.setInterfaces(new Class[] { targetClass });
              } else {
                  enhancer.setSuperclass(targetClass);
              }
              enhancer.setCallbackTypes(new Class[] { AsyncLoadServiceInterceptor.class, AsyncLoadDirect.class,
                      AsyncLoadInterceptor.class });
              enhancer.setCallbackFilter(new AsyncLoadCallbackFilter());
              proxyClass = enhancer.createClass();
              // 注册proxyClass
              AsyncLoadProxyRepository.registerProxy(targetClass.getName(), proxyClass);
          }
  
          Enhancer.registerCallbacks(proxyClass, new Callback[] { new AsyncLoadServiceInterceptor(),
                  new AsyncLoadDirect(), new AsyncLoadInterceptor() });
          try {
              return (T) AsyncLoadReflectionHelper.newInstance(proxyClass);
          } finally {
              // clear thread callbacks to allow them to be gc'd
              Enhancer.registerStaticCallbacks(proxyClass, null);
          }
      }
  
      // ====================== setter / getter ===========================
  
      public void setService(T service) {
          this.service = service;
          if (targetClass == null) {
              this.targetClass = (Class<T>) service.getClass();
          }
      }
  
      public void setConfig(AsyncLoadConfig config) {
          this.config = config;
      }
  
      public void setExecutor(AsyncLoadExecutor executor) {
          this.executor = executor;
      }
  
      public void setTargetClass(Class targetClass) {
          this.targetClass = targetClass;
      }
  
  }
  