AOP框架實現

本文參照《架構探險》一書。html

aop 無非是在原有的方法先後加入自定義的代碼。整體思想:java

  1. 經過cglib或jvm動態代理技術生成對目標方法的代理類
  2. 將容器中的原實例替換爲新生成的代理類實例

JDK動態代理只能對實現了接口的類生成代理,而不能針對類 。 CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法 。 由於是繼承,因此該類或方法最好不要聲明成final ,final能夠阻止繼承和多態。架構

<aop:aspectj-autoproxy proxy-target-class="true"/> 強制使用cglib作動態代理框架

AOP框架

public class AopHelper {
...
    static {
        try {
            //從容器中找到代理類和被代理類的關係
            Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();
            Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);

            for (Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet()) {
                //1.建立代理類
                Object proxy = ProxyManager.createProxy(targetEntry.getKey(), targetEntry.getValue());
                //2.將容器中的class 換爲 代理類
                BeanHelper.setBean(targetEntry.getKey(), proxy);

            }
        } catch (Exception e) {
            LOGGER.error("aop fail",e);
        }

    }	
  ...
}

切面類

@Aspect(Controller.class)
public class ControllerAspect extends AspectProxy

extends AspectProxy 實現父類方法,也就是咱們要添加的操做。jvm

@Aspect(Controller.class) 表示這個代理類代理的是哪一個類(具體方法代理規則能夠在代理類方法中判斷,作不一樣處理)ide

從容器中找到代理類和被代理類的關係

/**
    * class集合中找到指定切面的集合
    * @param aspect
    * @return
    * @throws Exception
    */
   private static Set<Class<?>> createTargetClassSet(Aspect aspect) throws Exception {
       Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
       Class<? extends Annotation> annotation = aspect.value();
       if (annotation != null && !annotation.equals(Aspect.class)) {
           targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
       }
       return targetClassSet;
   }

   /**
    * 找到繼承AspectProxy的代理類
    * 根據代理類的Aspect註解中value 找到被代理類
    * 返回代理類和被代理類的映射
    * proxyClass -> set<targetClass>
    * @return
    * @throws Exception
    */
   private static Map<Class<?>, Set<Class<?>>> createProxyMap() throws Exception {
       Map<Class<?>, Set<Class<?>>> proxyMap = new HashMap<>();

       //切面類
       Set<Class<?>> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
       for (Class<?> proxyCls : proxyClassSet) {
           if (proxyCls.isAnnotationPresent(Aspect.class)){//繼承了AspectProxy而且被Aspect標註
               Aspect aspect = proxyCls.getAnnotation(Aspect.class);
               Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
               proxyMap.put(proxyCls, targetClassSet);
           }
       }

       //添加事務代理
       addTransactionProxy(proxyMap);

       return proxyMap;
   }

   private static void addTransactionProxy(Map<Class<?>, Set<Class<?>>> proxyMap) {
       Set<Class<?>> serviceClassSet = ClassHelper.getClassSetByAnnotation(Service.class);
       proxyMap.put(TransactionProxy.class, serviceClassSet);
   }

   /**
    * targetClass -> List<proxy instance>
    * @param proxyMap
    * @return
    * @throws Exception
    */
   private static Map<Class<?>, List<Proxy>> createTargetMap(Map<Class<?>, Set<Class<?>>> proxyMap) throws Exception {
       HashMap<Class<?>, List<Proxy>> targetMap = new HashMap<>();
       for (Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()) {
           Class<?> proxyClass = proxyEntry.getKey();
           Set<Class<?>> targetClassSet = proxyEntry.getValue();
           for (Class<?> targetClass : targetClassSet) {
               Proxy proxy = (Proxy) proxyClass.newInstance();
               if (targetMap.containsKey(targetClass)) {
                   targetMap.get(targetClass).add(proxy);
               } else {
                   List<Proxy> proxyList = new ArrayList<>();
                   proxyList.add(proxy);
                   targetMap.put(targetClass, proxyList);
               }
           }
       }
       return targetMap;
   }

如何建立代理對象

//cglib 建立代理對象
public class ProxyManager {
    public static <T> T createProxy(final Class<T> targetClass, final List<Proxy> proxyList) {
        //CGLib提供建立代理對象,代理對象是一個代理鏈
        return (T) Enhancer.create(targetClass, new MethodInterceptor() {
            @Override
            public Object intercept(Object targetObject, Method targetMethod, Object[] methodParams, MethodProxy methodProxy) throws Throwable {
                //返回代理對象 代理鏈 的結果
                return new ProxyChain(targetClass, targetObject, targetMethod, methodProxy, methodParams, proxyList).doProxyChain();
            }
        });
    }
}

代理對象是ProxyChain類型,由於同一個class可能有多個aop須要處理,因此是一條鏈。this

Enhancer.create

ProxyChain的執行

public class ProxyChain {

    private final Class<?> targetClass;
    private final Object targetObject;
    private final Method targetMethod;
    private final MethodProxy methodProxy;
    private final Object[] methodParams;
    
  ...
    
    public Object doProxyChain() throws Throwable {
        Object methodResult;
        if (proxyIndex < proxyList.size()) {
            methodResult = proxyList.get(proxyIndex++).doProxy(this);
        } else {
            //最後執行目標對象的業務邏輯
            //方法代理,參數只傳入哪一個對象,什麼參數
            methodResult = methodProxy.invokeSuper(targetObject, methodParams);
        }
        return methodResult;
    }
}

代理對象

切面代理

public abstract class AspectProxy implements Proxy{
    private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class);

    @Override
    public Object doProxy(ProxyChain proxyChain) throws Throwable {
        Object result = null;
        Class<?> targetClass = proxyChain.getTargetClass();
        Object[] methodParams = proxyChain.getMethodParams();
        Method targetMethod = proxyChain.getTargetMethod();

        begin();

        try {
            if (intercept(targetClass, targetMethod, methodParams)) {
                before(targetClass, targetMethod, methodParams);
                result = proxyChain.doProxyChain();
                after(targetClass, targetMethod, methodParams, result);
            } else {
                result = proxyChain.doProxyChain();
            }
        } catch (Exception e) {
            LOGGER.error("proxy fail",e);
            error(targetClass, targetMethod, methodParams, e);
            throw e;
        } finally {
            end();
        }
        return result;
    }

    private void begin() {
    }

    public boolean intercept(Class<?> cls, Method method, Object[] params) {
        return true;
    }

    public void before(Class<?> cls, Method method, Object[] params) {

    }

    public void after(Class<?> cls, Method method, Object[] params, Object result) {

    }

    public void error(Class<?> cls, Method method, Object[] params, Throwable e) {

    }

    public void end() {}

}

事務代理

public class TransactionProxy implements Proxy {

    //保證同一線程中事務控制相關邏輯只會執行一次?
    private static final ThreadLocal<Boolean> FLAG_HOLDER = new ThreadLocal<Boolean>(){
        protected Boolean initialValue() {
            return false;
        }
    };

    @Override
    public Object doProxy(ProxyChain proxyChain) throws Exception, Throwable {
        Boolean flag = FLAG_HOLDER.get();
        Method method = proxyChain.getTargetMethod();
        Object result = null;
        if (!flag && method.isAnnotationPresent(Transaction.class)) {
            FLAG_HOLDER.set(true);
            try {
                DatabaseHelper.beginTransaction();
                LOGGER.debug("begin transaction");
                result = proxyChain.doProxyChain();
                DatabaseHelper.commitTransaction();
                LOGGER.debug("commit transaction");
            } catch (Exception e) {
                DatabaseHelper.rollbackTransaction();
                LOGGER.debug("rollback transaction");
                throw e;
            } finally {
                //DatabaseHelper.closeConnetion();
                FLAG_HOLDER.remove();
            }
        } else {
            result = proxyChain.doProxyChain();
        }
        return result;
    }
}

FLAG_HOLDER應該是防止事務的嵌套,好比兩個service都標註了@transaction,一個serviceA一個ServiceB, 可是ServiceA中又調用了ServiceB,這樣沒有FLAG_HOLDER就會先啓動A的事務,再啓動B的事務(A的事務還沒完)。加上FLAG_HOLDER就只會啓動A的事務,B看到已經有事務在執行就不啓動事務,默認加入了A的事務。.net

相關文章
相關標籤/搜索