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

📄 customizabletraceinterceptor.java

📁 有关此类编程有心德的高手 希望能够多多给予指教
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		this.exitMessage = exitMessage;
	}

	/**
	 * Set the template used for method exception log messages.
	 * This template can contain any of the following placeholders:
	 * <ul>
	 * <li><code>$[targetClassName]</code></li>
	 * <li><code>$[targetClassShortName]</code></li>
	 * <li><code>$[argumentTypes]</code></li>
	 * <li><code>$[arguments]</code></li>
	 * <li><code>$[exception]</code></li>
	 * </ul>
	 * @throws IllegalArgumentException if the message template is empty
	 * or contains any invalid placeholders
	 */
	public void setExceptionMessage(String exceptionMessage) {
		Assert.hasText(exceptionMessage, "'exceptionMessage' must not be empty");
		checkForInvalidPlaceholders(exceptionMessage);
		Assert.doesNotContain(exceptionMessage, PLACEHOLDER_RETURN_VALUE,
				"exceptionMessage cannot contain placeholder [" + PLACEHOLDER_RETURN_VALUE + "]");
		Assert.doesNotContain(exceptionMessage, PLACEHOLDER_INVOCATION_TIME,
				"exceptionMessage cannot contain placeholder [" + PLACEHOLDER_INVOCATION_TIME + "]");
		this.exceptionMessage = exceptionMessage;
	}


	/**
	 * Writes a log message before the invocation based on the value of <code>enterMessage</code>.
	 * If the invocation succeeds, then a log message is written on exit based on the value
	 * <code>exitMessage</code>. If an exception occurs during invocation, then a message is
	 * written based on the value of <code>exceptionMessage</code>.
	 * @see #setEnterMessage
	 * @see #setExitMessage
	 * @see #setExceptionMessage
	 */
	protected Object invokeUnderTrace(MethodInvocation invocation, Log logger) throws Throwable {
		String name = invocation.getMethod().getDeclaringClass().getName() + "." + invocation.getMethod().getName();
		StopWatch stopWatch = new StopWatch(name);
		Object returnValue = null;
		boolean exitThroughException = false;
		try {
			stopWatch.start(name);
			writeToLog(logger,
					replacePlaceholders(this.enterMessage, invocation, null, null, -1));
			returnValue = invocation.proceed();
			return returnValue;
		}
		catch (Throwable ex) {
			if(stopWatch.isRunning()) {
				stopWatch.stop();
			}
			exitThroughException = true;
			writeToLog(logger,
					replacePlaceholders(this.exceptionMessage, invocation, null, ex, stopWatch.getTotalTimeMillis()), ex);
			throw ex;
		}
		finally {
			if (!exitThroughException) {
				if(stopWatch.isRunning()) {
					stopWatch.stop();
				}
				writeToLog(logger,
						replacePlaceholders(this.exitMessage, invocation, returnValue, null, stopWatch.getTotalTimeMillis()));
			}
		}
	}

	/**
	 * Writes the supplied message to the supplied <code>Log</code> instance.
	 * @see #writeToLog(org.apache.commons.logging.Log, String, Throwable)
	 */
	protected void writeToLog(Log logger, String message) {
		writeToLog(logger, message, null);
	}

	/**
	 * Writes the supplied message and {@link Throwable} to the
	 * supplied <code>Log</code> instance. By default messages are written
	 * at <code>TRACE</code> level. Sub-classes can override this method
	 * to control which level the message is written at.
	 */
	protected void writeToLog(Log logger, String message, Throwable ex) {
		if (ex != null) {
			logger.trace(message, ex);
		}
		else {
			logger.trace(message);
		}
	}

	/**
	 * Replace the placeholders in the given message with the supplied values,
	 * or values derived from those supplied.
	 * @param message the message template containing the placeholders to be replaced
	 * @param methodInvocation the <code>MethodInvocation</code> being logged.
	 * Used to derive values for all placeholders except <code>$[exception]</code>
	 * and <code>$[returnValue]</code>.
	 * @param returnValue any value returned by the invocation.
	 * Used to replace the <code>$[returnValue]</code> placeholder. May be <code>null</code>.
	 * @param throwable any <code>Throwable</code> raised during the invocation.
	 * The value of <code>Throwable.toString()</code> is replaced for the
	 * <code>$[exception]</code> placeholder. May be <code>null</code>.
	 * @param invocationTime the value to write in place of the
	 * <code>$[invocationTime]</code> placeholder
	 * @return the formatted output to write to the log
	 */
	protected String replacePlaceholders(String message, MethodInvocation methodInvocation,
			Object returnValue, Throwable throwable, long invocationTime) {

		Matcher matcher = PATTERN.matcher(message);

		StringBuffer output = new StringBuffer();
		while (matcher.find()) {
			String match = matcher.group();
			if (PLACEHOLDER_METHOD_NAME.equals(match)) {
				matcher.appendReplacement(output, methodInvocation.getMethod().getName());
			}
			else if (PLACEHOLDER_TARGET_CLASS_NAME.equals(match)) {
				String targetClassName = escape(methodInvocation.getThis().getClass().getName());
				matcher.appendReplacement(output, targetClassName);
			}
			else if (PLACEHOLDER_TARGET_CLASS_SHORT_NAME.equals(match)) {
				matcher.appendReplacement(output, escape(ClassUtils.getShortName(methodInvocation.getThis().getClass())));
			}
			else if (PLACEHOLDER_ARGUMENTS.equals(match)) {
				matcher.appendReplacement(output, escape(StringUtils.arrayToCommaDelimitedString(methodInvocation.getArguments())));
			}
			else if (PLACEHOLDER_ARGUMENT_TYPES.equals(match)) {
				appendArgumentTypes(methodInvocation, matcher, output);
			}
			else if (PLACEHOLDER_RETURN_VALUE.equals(match)) {
				appendReturnValue(methodInvocation, matcher, output, returnValue);
			}
			else if (throwable != null && PLACEHOLDER_EXCEPTION.equals(match)) {
				matcher.appendReplacement(output, throwable.toString());
			}
			else if (PLACEHOLDER_INVOCATION_TIME.equals(match)) {
				matcher.appendReplacement(output, Long.toString(invocationTime));
			}
			else {
				// Should not happen since placeholders are checked earlier.
				throw new IllegalArgumentException("Unknown placeholder [" + match + "]");
			}
		}
		matcher.appendTail(output);

		return output.toString();
	}

	/**
	 * Adds the <code>String</code> representation of the method return value
	 * to the supplied <code>StringBuffer</code>. Correctly handles
	 * <code>null</code> and <code>void</code> results.
	 * @param methodInvocation the <code>MethodInvocation</code> that returned the value
	 * @param matcher the <code>Matcher</code> containing the matched placeholder
	 * @param output the <code>StringBuffer</code> to write output to
	 * @param returnValue the value returned by the method invocatio.
	 */
	private void appendReturnValue(
			MethodInvocation methodInvocation, Matcher matcher, StringBuffer output, Object returnValue) {

		if (methodInvocation.getMethod().getReturnType() == void.class) {
			matcher.appendReplacement(output, "void");
		}
		else if (returnValue == null) {
			matcher.appendReplacement(output, "null");
		}
		else {
			matcher.appendReplacement(output, escape(returnValue.toString()));
		}
	}

	/**
	 * Adds a comma-separated list of the short <code>Class</code> names of the
	 * method argument types to the output. For example, if a method has signature
	 * <code>put(java.lang.String, java.lang.Object)</code> then the value returned
	 * will be <code>String, Object</code>.
	 * @param methodInvocation the <code>MethodInvocation</code> being logged.
	 * Arguments will be retreived from the corresponding <code>Method</code>.
	 * @param matcher the <code>Matcher</code> containing the state of the output
	 * @param output the <code>StringBuffer</code> containing the output
	 */
	private void appendArgumentTypes(MethodInvocation methodInvocation, Matcher matcher, StringBuffer output) {
		Class[] argumentTypes = methodInvocation.getMethod().getParameterTypes();
		String[] argumentTypeShortNames = new String[argumentTypes.length];
		for (int i = 0; i < argumentTypeShortNames.length; i++) {
			argumentTypeShortNames[i] = ClassUtils.getShortName(argumentTypes[i]);
		}
		matcher.appendReplacement(output, escape(StringUtils.arrayToCommaDelimitedString(argumentTypeShortNames)));
	}

	/**
	 * Checks to see if the supplied <code>String</code> has any placeholders
	 * that are not specified as constants on this class and throws an
	 * <code>IllegalArgumentException</code> if so.
	 */
	private void checkForInvalidPlaceholders(String message) throws IllegalArgumentException {
		Matcher matcher = PATTERN.matcher(message);
		while (matcher.find()) {
			String match = matcher.group();
			if (!ALLOWED_PLACEHOLDERS.contains(match)) {
				throw new IllegalArgumentException("Placeholder [" + match + "] is not valid");
			}
		}
	}

	/**
	 * Replaces <code>$</code> in inner class names with <code>\$</code>.
	 */
	private String escape(String input) {
		Matcher matcher = ESCAPE_PATTERN.matcher(input);
		StringBuffer output = new StringBuffer(input.length());
		while (matcher.find()) {
			matcher.appendReplacement(output, "");
            output.append("\\").append(matcher.group());
		}
		matcher.appendTail(output);
		return output.toString();
	}

}

⌨️ 快捷键说明

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