《架构探险》之面向切面编程(AOP)(下)

阅读更多

        spring主要的特点之一就是面向切面编程,为了实现切面编程需要借助动态代理技术。

        首先,定义一个代理管理类,用来创建创建的代理,在代理中调用切面的实现逻辑:

public class ProxyManager {

    public static  T createProxy(final Class targetClass, final List proxyList){
        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();
            }
        });
    }
}

         多个切面使用链表来管理,组成一个切面链,:

public Object doProxyChain() throws Throwable {
    Object methodResult;
    if(proxyIndex < proxyList.size()){
        Proxy proxy = proxyList.get(proxyIndex);
        proxyIndex++;
        methodResult = proxy.doProxy(this);
    }else {
        methodResult = methodProxy.invokeSuper(targetObject,      methodParams);
    }

    return methodResult;
}

         以事务切面的实现为例:

public class TransactionAspect extends AspectProxy {

    private static final Logger LOGGER = LoggerFactory.getLogger(AspectProxy.class);
    private static final ThreadLocal FLAG_HOLDER = new ThreadLocal();

    @Override
    public final Object doProxy(ProxyChain proxyChain)throws Throwable{
        Object result = null;

        Method method = proxyChain.getTargetMethod();
        Boolean flag = FLAG_HOLDER.get();
        if(flag == null && method.isAnnotationPresent(Transaction.class)){
            try {
                  FLAG_HOLDER.set(true);
                  DatabaseHelper.beginTransaction();
                  result = proxyChain.doProxyChain();
                  DatabaseHelper.endTransaction();
            } catch (Exception e) {
                  LOGGER.error("proxy failure", e);
                  DatabaseHelper.rollbackTransaction();
                  throw e;
            } finally {
                  FLAG_HOLDER.remove();
            }
         }else {
             result = proxyChain.doProxyChain();
         }

        return result;
    }

}

        接下来,就需要在框架的对象管理池中在切点出使用动态代理替代原有的对象,这样当调用对象方法时会去调用代理的处理逻辑,实现面向切面的编程。

//根据代理类找到目标类,然后反过来对目标类生成代理类(链)

static {
    try {
        Map, Set>> proxyMap = createProxyMap();
        Map, List> targetMap = createTargetMap(proxyMap);
        for(Map.Entry, List> targetEntry : targetMap.entrySet()){
            Class targetClass = targetEntry.getKey();
            List proxyList = targetEntry.getValue();
            Object proxy = ProxyManager.createProxy(targetClass, proxyList);
            BeanHelper.setBean(targetClass, proxy);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static Set> createTargetClassSet(Aspect aspect){
    Set> targetClassSet = new HashSet>();
    Class annotation = aspect.value();
    if(annotation != null && !annotation.equals(Aspect.class)){
        targetClassSet.addAll(ClassHelper.getClassSetByAnnotation(annotation));
    }

    return targetClassSet;
}

private static Map, Set>> createProxyMap(){
    Map, Set>> proxyMap = new HashMap, Set>>();
    Set> proxyClassSet = ClassHelper.getClassSetBySuper(AspectProxy.class);
    for(Class proxyClass : proxyClassSet){
        if(proxyClass.isAnnotationPresent(Aspect.class)){
            Aspect aspect = proxyClass.getAnnotation(Aspect.class);
            Set> targetClassSet = createTargetClassSet(aspect);
            proxyMap.put(proxyClass, targetClassSet);
        }
    }
    Set> transactionServiceSet = ClassHelper.getClassSetByAnnotation(Service.class);
    proxyMap.put(TransactionAspect.class, transactionServiceSet);

    return proxyMap;
}

private static Map, List> createTargetMap(Map, Set>> proxyMap) throws IllegalAccessException, InstantiationException {
    Map, List> targetMap = new HashMap, List>();
    for(Map.Entry, Set>> proxyEntry : proxyMap.entrySet()){
        Class proxyClass = proxyEntry.getKey();
        Set> targetClassSet = proxyEntry.getValue();
        for(Class targetClass : targetClassSet){
            Proxy proxy = (Proxy) proxyClass.newInstance();
            if(targetMap.containsKey(targetClass)){
                targetMap.get(targetClass).add(proxy);
            }else {
                List proxyList = new ArrayList();
                proxyList.add(proxy);
                targetMap.put(targetClass, proxyList);
            }
        }
    }

    return targetMap;
}

 

 

你可能感兴趣的:(架构,AOP,事务,Spring)