All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.support.project.aop.Intercepter Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
package org.support.project.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.support.project.common.log.Log;
import org.support.project.common.log.LogFactory;
import org.support.project.ormapping.dao.AbstractDao;
import org.support.project.ormapping.transaction.Transaction;

import javassist.util.proxy.MethodHandler;

public class Intercepter implements InvocationHandler, MethodHandler {
    /** ログ */
    private static Log logger = LogFactory.getLog(Intercepter.class);

    private Object target;
    private Class intf;

    public Intercepter(Class intf, final Object target) {
        this.target = target;
        this.intf = intf;
    }

    /**
     * インタフェースの実行
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            Aspect aspect = intf.getAnnotation(Aspect.class);
            if (aspect != null) {
                // クラスにAspectが登録されていればそれを実行(そしてリターン)
                Class adviceClass = aspect.advice();
                Advice advice = adviceClass.newInstance();
                Object ret = advice.invoke(target, method, args);
                return ret;
            }

            aspect = method.getAnnotation(Aspect.class);
            if (aspect != null) {
                // メソッドにAspectが登録されていればそれを実行(そしてリターン)
                Class adviceClass = aspect.advice();
                Advice advice = adviceClass.newInstance();
                Object ret = advice.invoke(target, method, args);
                return ret;
            }

            Method intfMethod = getAnnotationMethod(method.getName(), method.getParameterTypes());
            if (intfMethod != null) {
                aspect = intfMethod.getAnnotation(Aspect.class);
                if (aspect != null) {
                    Class adviceClass = aspect.advice();
                    Advice advice = adviceClass.newInstance();
                    Object ret = advice.invoke(target, method, args);
                    return ret;
                }
            }

            // 何も登録されていない場合、通常処理
            if (logger.isTraceEnabled()) {
                logger.trace("[BEGIN] " + target.getClass() + " : " + method.getName());
            }

            // 実際のコードを呼び出し
            Object ret = method.invoke(target, args);

            if (logger.isTraceEnabled()) {
                logger.trace("[END] " + target.getClass() + " : " + method.getName());
            }
            return ret;
        } catch (Throwable e) {
            if (logger.isDebugEnabled()) {
                logger.debug("[ERROR] " + target.getClass() + " : " + method.getName() + " : " + e.getMessage());
            }
            throw e;
        }
    }

    private Method getAnnotationMethod(String name, Class[] parameterTypes) {
        Method m;
        m = getMethod(intf, name, parameterTypes);
        if (m != null) {
            Aspect aspect = m.getAnnotation(Aspect.class);
            if (aspect != null) {
                return m;
            }
        }
        m = getMethod(target.getClass(), name, parameterTypes);
        if (m != null) {
            Aspect aspect = m.getAnnotation(Aspect.class);
            if (aspect != null) {
                return m;
            }
        }
        return null;
    }

    /**
     * 実行するメソッドの検索
     * 
     * @param clazz
     *            メソッドを検索するクラス
     * @param methodName
     *            メソッド名
     * @param parameterTypes
     *            メソッドの引数の型
     * @return メソッド
     */
    private Method getMethod(Class clazz, String methodName, Class[] parameterTypes) {
        Method[] methods = clazz.getDeclaredMethods();
        // boolean exist = false;
        List list = new ArrayList();

        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                list.add(method);
            }
        }
        if (!list.isEmpty()) {
            if (list.size() == 1) {
                return list.get(0);
            } else {
                // Privateメソッドを取得する場合、getDeclaredMethodメソッドを使用します。
                Method method;
                try {
                    method = clazz.getDeclaredMethod(methodName, parameterTypes);
                } catch (NoSuchMethodException | SecurityException e) {
                    // throw new SystemException(e);
                    return null;
                }
                return method;
            }
        } else {
            // 親クラスに定義されていないか再帰的に検索
            if (clazz.getSuperclass() != null) {
                return getMethod(clazz.getSuperclass(), methodName, parameterTypes);
            } else {
                // throw new SystemException(new NoSuchMethodException("methodName"));
                return null;
            }
        }
    }

    /**
     * クラスの実行
     */
    @Override
    public Object invoke(Object proxy, Method method, Method proceed, Object[] args) throws Throwable {
        try {
            Aspect aspect = intf.getAnnotation(Aspect.class);
            if (aspect != null) {
                // クラスにAspectが登録されていればそれを実行(そしてリターン)
                Class adviceClass = aspect.advice();
                Advice advice = adviceClass.newInstance();
                Object ret = advice.invoke(target, proceed, args);
                return ret;
            }
            // proceedはContainerで取得してProxyでくるんだMethodなので、アノテーションが設定されることは無い
            // aspect = proceed.getAnnotation(Aspect.class);
            // if (aspect != null) {
            // Class adviceClass = aspect.advice();
            // Advice advice = adviceClass.newInstance();
            // Object ret = advice.invoke(target, proceed, args);
            // return ret;
            // }

            aspect = method.getAnnotation(Aspect.class);
            if (aspect != null) {
                Class adviceClass = aspect.advice();
                Advice advice = adviceClass.newInstance();
                Object ret = advice.invoke(target, proceed, args);
                return ret;
            }

            // 何も登録されていないが、クラスがAbstractDaoを継承している場合
            if (target instanceof AbstractDao) {
                // NewTransactionが設定されていない場合、デフォルトでトランザクションを引き継ぐ
                Advice advice = new Transaction();
                Object ret = advice.invoke(target, proceed, args);
                return ret;
            }

            // 何も登録されていない場合、通常処理
            if (logger.isTraceEnabled()) {
                logger.trace("[BEGIN] " + proxy.getClass() + " : " + method.getName());
            }

            // 実際のコードを呼び出し
            Object ret = proceed.invoke(proxy, args);
            // Object ret = method.invoke(proxy, args);

            if (logger.isTraceEnabled()) {
                logger.trace("[END] " + proxy.getClass() + " : " + method.getName());
            }
            return ret;
        } catch (Throwable e) {
            if (e instanceof InvocationTargetException) {
                InvocationTargetException invocationTargetException = (InvocationTargetException) e;
                Throwable throwable = invocationTargetException.getTargetException();
                if (logger.isInfoEnabled()) {
                    StringBuilder builder = new StringBuilder();
                    builder.append("error. [object]").append(proxy.getClass().toString()).append("[proceed]").append(proceed.getName());
                    if (args != null) {
                        int count = 0;
                        for (Object param : args) {
                            builder.append("[param").append(count++).append("]").append(param);
                        }
                    }
                    builder.append("\n[throwable.getMessage()] ").append(throwable.getMessage());
                    logger.info(builder.toString());
                }
                throw throwable;
            } else {
                if (logger.isInfoEnabled()) {
                    logger.info("[ERROR] " + proxy.getClass() + " : " + method.getName() + " : " + e.getMessage());
                    if (e.getCause() != null) {
                        logger.info("  ", e.getCause());
                    }
                }
            }
            throw e;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy