com.bstek.dorado.util.proxy.MethodInterceptorDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for com.bstek.dorado.util.proxy.MethodInterceptorDispatcher.java

Source

/*
 * This file is part of Dorado 7.x (http://dorado7.bsdn.org).
 * 
 * Copyright (c) 2002-2012 BSTEK Corp. All rights reserved.
 * 
 * This file is dual-licensed under the AGPLv3 (http://www.gnu.org/licenses/agpl-3.0.html) 
 * and BSDN commercial (http://www.bsdn.org/licenses) licenses.
 * 
 * If you are unsure which license is appropriate for your use, please contact the sales department
 * at http://www.bstek.com/contact.
 */

package com.bstek.dorado.util.proxy;

import java.io.Serializable;
import java.lang.reflect.Method;

import javassist.util.proxy.MethodHandler;
import net.sf.cglib.proxy.MethodProxy;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * ?
 * <p>
 * ?net.sf.cglib.proxy.MethodInterceptor
 * ?org.aopalliance.intercept.MethodInterceptor
 * ?????org.aopalliance.intercept.MethodInterceptor
 * ??CglibSpring AOP???????
 * </p>
 * 
 * @author Benny Bao (mailto:benny.bao@bstek.com)
 * @since Dec 28, 2007
 */
public abstract class MethodInterceptorDispatcher
        implements MethodInterceptor, net.sf.cglib.proxy.MethodInterceptor, MethodHandler {
    private static final Log logger = LogFactory.getLog(MethodInterceptorDispatcher.class);

    private static final String WRITE_REPLACE = "writeReplace";
    private static Method EQUALS_METHOD;

    static {
        try {
            EQUALS_METHOD = Object.class.getDeclaredMethod("equals", new Class[] { Object.class });
        } catch (Exception e) {
            logger.warn(e, e);
        }
    }

    private static class FinalAopallianceMethodInterceptor implements MethodInterceptor {
        private MethodInvocation originMethodInvocation;

        public FinalAopallianceMethodInterceptor(MethodInvocation originMethodInvocation) {
            this.originMethodInvocation = originMethodInvocation;
        }

        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            return originMethodInvocation.proceed();
        }
    }

    private static class FinalCglibMethodInterceptor implements MethodInterceptor {
        private MethodProxy methodProxy;

        public FinalCglibMethodInterceptor(MethodProxy methodProxy) {
            this.methodProxy = methodProxy;
        }

        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            return methodProxy.invokeSuper(methodInvocation.getThis(), methodInvocation.getArguments());
        }
    }

    private static class FinalJavassistMethodInterceptor implements MethodInterceptor {
        private Method procssed;

        public FinalJavassistMethodInterceptor(Method procssed) {
            this.procssed = procssed;
        }

        public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            return procssed.invoke(methodInvocation.getThis(), methodInvocation.getArguments());
        }
    }

    private MethodInterceptor[] subMethodInterceptors;

    /**
     * ?
     */
    public MethodInterceptor[] getSubMethodInterceptors() {
        return subMethodInterceptors;
    }

    public void setSubMethodInterceptors(MethodInterceptor[] subMethodInterceptors) {
        this.subMethodInterceptors = subMethodInterceptors;
    }

    public abstract MethodInterceptorFilter getMethodInterceptorFilter(Object object, Method method, Object[] args);

    /**
     * org.aopalliance.intercept.
     * MethodInterceptorinvokeMethodInvocation?
     * 
     * @param object
     *            ?
     * @param method
     *            ?
     * @param args
     *            ??
     * @param methodInterceptorChain
     *            ??
     *            {@link #createFinalMethodInterceptor(MethodProxy)}
     */
    protected abstract MethodInvocation createMethodInvocation(Object object, Method method, Object[] args,
            MethodInterceptorChain methodInterceptorChain);

    protected MethodInterceptor createFinalAopallianceMethodInterceptor(MethodInvocation methodInvocation) {
        return new FinalAopallianceMethodInterceptor(methodInvocation);
    }

    protected MethodInterceptor createCglibFinalMethodInterceptor(MethodProxy methodProxy) {
        return new FinalCglibMethodInterceptor(methodProxy);
    }

    protected MethodInterceptor createJavassistFinalMethodInterceptor(Method method, Method procssed) {
        return new FinalJavassistMethodInterceptor(procssed);
    }

    protected boolean filterMethod(Method method) {
        return true;
    }

    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        Object object = methodInvocation.getThis();
        Method method = methodInvocation.getMethod();
        Object[] arguments = methodInvocation.getArguments();

        if (subMethodInterceptors != null && filterMethod(method)) {
            MethodInterceptorChain methodInterceptorChain = new MethodInterceptorChain(subMethodInterceptors,
                    createFinalAopallianceMethodInterceptor(methodInvocation),
                    getMethodInterceptorFilter(object, method, arguments));

            MethodInvocation mockMethodInvocation = createMethodInvocation(object, method, arguments,
                    methodInterceptorChain);
            MethodInterceptor methodInterceptor = methodInterceptorChain.next(mockMethodInvocation);
            return methodInterceptor.invoke(mockMethodInvocation);
        } else {
            return methodInvocation.proceed();
        }
    }

    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // ??equals()?dorado??AOP??
        if (method.equals(EQUALS_METHOD)) {
            Object proxyTarget = ProxyBeanUtils.getProxyTarget(args[0]);
            if (proxyTarget == object)
                return Boolean.TRUE;
            args = new Object[] { proxyTarget };
        }

        if (subMethodInterceptors != null && filterMethod(method)) {
            MethodInterceptorChain methodInterceptorChain = new MethodInterceptorChain(subMethodInterceptors,
                    createCglibFinalMethodInterceptor(methodProxy),
                    getMethodInterceptorFilter(object, method, args));

            MethodInvocation mockMethodInvocation = createMethodInvocation(object, method, args,
                    methodInterceptorChain);
            MethodInterceptor methodInterceptor = methodInterceptorChain.next(mockMethodInvocation);
            return methodInterceptor.invoke(mockMethodInvocation);
        } else {
            return methodProxy.invokeSuper(object, args);
        }
    }

    protected Object getObjectForSerialization(Object object) throws Exception {
        Class<?> cl = ProxyBeanUtils.getProxyTargetType(object);
        if (cl != object.getClass()) {
            Object beanForSerialization = cl.newInstance();
            PropertyUtils.copyProperties(beanForSerialization, object);
            return beanForSerialization;
        } else {
            return object;
        }
    }

    public Object invoke(Object object, Method method, Method procssed, Object[] args) throws Throwable {
        if (method.equals(EQUALS_METHOD)) {
            Object proxyTarget = ProxyBeanUtils.getProxyTarget(args[0]);
            if (proxyTarget == object)
                return Boolean.TRUE;
            args = new Object[] { proxyTarget };
        } else if (object instanceof Serializable && method.getName().equals(WRITE_REPLACE)
                && method.getReturnType().equals(Object.class)) {
            try {
                Class<?> realClass = ProxyBeanUtils.getProxyTargetType(object);
                realClass.getMethod(WRITE_REPLACE, new Class<?>[0]);
            } catch (NoSuchMethodException e) {
                return getObjectForSerialization(object);
            }
        }

        if (subMethodInterceptors != null && filterMethod(method)) {
            MethodInterceptorChain methodInterceptorChain = new MethodInterceptorChain(subMethodInterceptors,
                    createJavassistFinalMethodInterceptor(method, procssed),
                    getMethodInterceptorFilter(object, method, args));

            MethodInvocation mockMethodInvocation = createMethodInvocation(object, method, args,
                    methodInterceptorChain);
            MethodInterceptor methodInterceptor = methodInterceptorChain.next(mockMethodInvocation);
            return methodInterceptor.invoke(mockMethodInvocation);
        } else {
            return procssed.invoke(object, args);
        }
    }
}