⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exceptionhandling.aj

📁 java的异常处理 java的异常处理
💻 AJ
字号:
package exception;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Stack;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.CodeSignature;

/**
 * Normalizes Exception Handling within the application, based
 * on the Fault/Contingency/Barrier model. The aspect addresses
 * these concerns:
 * <ul>
 * <li>Capturing diagnostic information for fault conditions,
 * including a trace of method calls leading to the fault with
 * arguments and their values.
 * <li>Ensuring that fault exceptions reach the handler in the
 * Fault Barrier, regardless of the actions of intervening
 * methods.
 * <li>Translating uncaught Runtime execeptions to
 * FaultExceptions, ensuring that they are logged as faults and
 * ensuring that the Fault Barrier receives them.
 * <li>Compile-time detection of departures from the model such
 * as throwing a checked exception that is not a subclass of
 * ContingencyException.
 * </ul>
 * 
 * @author Barry Ruzek
 */
public abstract aspect ExceptionHandling {

    /*
     * Compile-time exception policy enforcement is implemented
     * here. A method or constructor may not declare that it
     * throws a checked exception other than
     * ContingencyException or one of its subclasses. This
     * restriction forces methods and constructors to catch and
     * handle checked exceptions from APIs that they use such as
     * SQLException or IOException. This aspect does not specify
     * what those methods do with those checked exceptions, only
     * that they may never allowed to propagate past the method
     * boundary.
     */

    pointcut methodViolation():
        execution(* *(..) throws (Exception+ 
            && !ContingencyException+ 
            && !RuntimeException+));

    declare error: 
        methodViolation(): 
            "Method throws a checked exception that is not a ContingencyException";

    pointcut constructorViolation():
        execution(*.new(..) throws (Exception+ 
            && !ContingencyException+ 
            && !RuntimeException+));

    declare error: 
        constructorViolation(): 
            "Constructor throws a checked exception that is not a ContingencyException";

    /**
     * Pointcut that determines where Exception advice is
     * applied. Advice is applied to all methods in the
     * application except when those methods are invoked during
     * the execution of this advice. Methods in the application
     * may be invoked during advice processing. The pointcut
     * includes these join points:
     * <ul>
     * <li>All Method executions
     * <li>All Constructor executions
     * <li>All Object initializations
     * <li>All Object pre-initializations
     * <li>All Class initializations
     * </ul>
     * The pointcut excludes these join points:
     * <ul>
     * <li>Any join point within the lexical scope of this
     * aspect
     * <li>Any join point within the lexical scope of
     * subaspects
     * <li>Any join point in the control flow of advice
     * execution
     * </ul>
     */
    pointcut exceptionAdvicePoints(): 
           (execution (* *.*(..))
         || execution (*.new(..))
         || initialization(*.new(..))          
         || preinitialization(*.new(..))        
         || staticinitialization(*))
         && !within(ExceptionHandling+)                   
         && !cflow(adviceexecution());

    /**
     * Advice for detecting uncaught Throwables and translating
     * them to FaultExceptions. This produces uniform treatment
     * of fault conditions, making the job of the fault barrier
     * easier. Any uncaught Throwable that is defined in the our
     * exception model is considered to be a fault, and gets
     * wrapped inside a new FaultException. Catching uncaught
     * RuntimeExceptions is not enough because the JVM will
     * throw Error types during static initialization if it
     * finds a problem. Since our pointcut includes static
     * initialization the advice here needs to handle Error
     * types, too. That is, any Throwable.
     */
    after() throwing(Throwable throwable):exceptionAdvicePoints(){
        if (!(throwable instanceof FaultException || throwable instanceof ContingencyException)) {
            throw new FaultException("Unhandled exception: ",
                throwable);
        }
    }

    /**
     * Pointcut that picks out all exception handlers in the
     * application, regardless of the Throwable class they are
     * catching. The pointcut exposes the object that the
     * handler resides in and the Throwable object that is being
     * caught.
     */
    pointcut allHandlers(Object handlerType, Throwable throwable): 
            handler(Throwable+) && args(throwable) && this(handlerType);

    /**
     * Advice that guarantees that FaultExceptions are caught by
     * methods within classes that are designated Fault
     * Barrriers. If an undesignated method inadvertently
     * catches a FaultException (by catching Exception, for
     * example) the FaultException will be re-thrown until it
     * reaches a handler in a class designated to contain a
     * FaultBarrier.
     */
    before(Object handler, Throwable throwable): 
        allHandlers(handler, throwable) {
        if (throwable instanceof FaultException) {
            if (!(isFaultBarrier(handler))) {
                FaultException fault = (FaultException) throwable;
                throw (fault);
            }
        }
    }

    /**
     * Integrates this aspect with a particular application by
     * allowing the application to judge whether an object
     * catching a FaultException is a designated Fault Barrier.
     * Subaspects implement this method to integrate operation
     * with a particular application.
     * 
     * @param exceptionHandler
     *            The object about to catch a FaultException.
     * @return True if the object is a designated Fault Barrier
     *         for the application, otherwise false.
     */
    abstract boolean isFaultBarrier(Object exceptionHandler);

    /**
     * Introduces a flag into the FaultException class that
     * allows the advice in this aspect to detect when it has
     * already created the log entry for a FaultException.
     * AfterThrowing advice runs for every method on the call
     * stack as the FaultException propagates until it is caught
     * by the Fault Barrier.
     */
    private boolean FaultException.logged = false;

    /**
     * Determines if a FaultException has already been logged.
     * 
     * @return True If the aspect has already logged the Fault,
     *         otherwise false.
     */
    private boolean FaultException.isLogged() {
        return this.logged;
    }

    /**
     * Marks the FaultException as logged.
     */
    private void FaultException.setLogged() {
        this.logged = true;
    }

    /**
     * Advice for detecting FaultExceptions and logging the
     * diagnostic information they contain. This method uses the
     * flag in the FaultException class introduced by this
     * aspect to avoid logging the same fault exception multiple
     * times as it is thrown outward to calling methods.
     */
    after() throwing(FaultException fault): exceptionAdvicePoints(){
        if (!fault.isLogged()) {
            logFault(fault);
            fault.setLogged();
        }
    }

    /**
     * This aspect maintains a trace stack of JoinPoint objects,
     * local to each thread that traverses the application. This
     * stack is maintained by advice that executes before and
     * after method executions. The trace of JoinPoints enables
     * method calls, parameter names, types, and values to be
     * added to the diagnostic information this aspect logs when
     * a fault condition is detected.
     */
    private static ThreadLocal<Stack<JoinPoint>> traceStack = new ThreadLocal<Stack<JoinPoint>>() {
        protected Stack<JoinPoint> initialValue() {
            return new Stack<JoinPoint>();
        }
    };

    /**
     * Pushes a JoinPoint onto the trace stack.
     * 
     * @param joinPoint
     *            The JoinPoint to add.
     */
    private static void pushJoinPoint(JoinPoint joinPoint) {
        traceStack.get().push(joinPoint);
    }

    /**
     * Pops a JoinPoint from the trace stack.
     */
    private static JoinPoint popJoinPoint() {
        Stack<JoinPoint> stack = traceStack.get();
        if (stack.empty()) {
            return null;
        } else {
            JoinPoint joinPoint = stack.pop();
            return joinPoint;
        }
    }

    /**
     * Obtains a snapshot of the current contents of the trace
     * stack.
     */
    private static JoinPoint[] getJoinPointTrace() {
        Stack<JoinPoint> stack = traceStack.get();
        return stack.toArray(new JoinPoint[stack.size()]);
    }

    /**
     * Advice that pushes the class, method, and argument values
     * onto the trace stack before a working method runs.
     */
    before(): exceptionAdvicePoints(){
        pushJoinPoint(thisJoinPoint);
    }

    /**
     * Advice that pops the class, method, and argument values
     * from the trace stack after a working method runs.
     */
    after(): exceptionAdvicePoints(){
        popJoinPoint();
    }

    /**
     * Records the diagnostic information contained in a
     * FaultException and the thread local trace stack
     * maintained by this aspect.
     * 
     * @param fault
     *            The fault exception to log.
     */
    private void logFault(FaultException fault) {
        ByteArrayOutputStream traceInfo = new ByteArrayOutputStream();
        PrintStream traceStream = new PrintStream(traceInfo);
        fault.printStackTrace(traceStream);
        StringBuffer applicationTrace = new StringBuffer();
        JoinPoint[] joinPoints = getJoinPointTrace();
        for (int i = joinPoints.length - 1; i >= 0; i--) {
            applicationTrace.append("\n\t"
                            + formatJoinPoint(joinPoints[i]));
        }
        recordFaultDiagnostics("Application Fault Detected"
                        + "\n" + traceInfo.toString()
                        + "\nApplication Trace:"
                        + applicationTrace.toString());
    }

    /**
     * The aspect invokes this abstract method to record the
     * fault diagnostics that it generates upon fault detection.
     * Subaspects supply concrete behavior for this recording,
     * allowing applications to decide how the recording
     * happens.
     * 
     * @param diagnostics
     *            The diagnotic string, generated by this aspect
     *            that must be recorded.
     */
    abstract void recordFaultDiagnostics(String diagnostics);

    /**
     * Produces a string that contains the executing class,
     * method, and argument names, types, and values that are
     * present in a JointPoint object. The format is:
     * class.method(arg:type=value, ..., arg:type=value)
     * 
     * @param joinPoint
     *            The joint point.
     * @return The formatted join point information.
     */
    private String formatJoinPoint(JoinPoint joinPoint) {
        CodeSignature signature = (CodeSignature) joinPoint.getSignature();
        String[] names = signature.getParameterNames();
        Class[] types = signature.getParameterTypes();
        Object[] args = joinPoint.getArgs();
        StringBuffer argumentList = new StringBuffer();
        for (int i = 0; i < args.length; i++) {
            if (argumentList.length() != 0) {
                argumentList.append(", ");
            }
            argumentList.append(names[i]);
            argumentList.append(":");
            argumentList.append(types[i].getName());
            argumentList.append("=");
            argumentList.append(args[i]);
        }
        StringBuffer format = new StringBuffer();

        format.append(joinPoint.getKind());
        format.append(": ");
        format.append(signature.getDeclaringTypeName());
        format.append(".");
        format.append(signature.getName());
        format.append("(");
        format.append(argumentList);
        format.append(")");
        return format.toString();
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -