java - 使用方面记录 java 中方法的进入、退出和异常

标签 java spring logging aop java.util.logging

我使用下面的代码来记录使用方面的进入、退出和异常。这样,我必须在 ApplicationContext 中为应用程序中的每个类定义一个 bean,并且维护如此长度的 bean 定义及其属性变得很麻烦。你能帮我简化这个吗?我认为每次创建类时都定义 bean 是不合适的设计。感谢帮助,提前致谢。

<bean id="logEntryBean" class="com.example.logging.LogEntry" />
<bean id="logExitBean" class="com.example.logging.LogReturn" />
<bean id="logExceptionBean" class ="com.example.logging.ExceptionLogger"/>

<bean id="simpleServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="simpleServiceBean" />
    <property name="interceptorNames">
        <list>
            <value>logEntryBean</value>
            <value>logExitBean</value>
            <value>logExceptionBean</value>
        </list>
    </property>
</bean>

    <bean id="secondServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="secondServiceBean" />
    <property name="interceptorNames">
        <list>
            <value>logEntryBean</value>
            <value>logExitBean</value>
            <value>logExceptionBean</value>
        </list>
    </property>
</bean>

==================== LogEntry类:

public class LogEntry implements MethodBeforeAdvice {
private final static Logger logger = Logger.getLogger(LogEntry.class);

public void before(Method method, Object[] args, Object target) throws Throwable {

    if(logger.isDebugEnabled())
    logger.info("logged entry for method : " + method.getName());
}

========================== LogReturn类:

public class LogReturn implements AfterReturningAdvice {
private final static Logger logger = Logger.getLogger(LogReturn.class);

public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    if(logger.isDebugEnabled())
    logger.info("Logged exit for method : " + method.getName());
}

================================ 异常记录器类

public void afterThrowing(Exception r) throws Throwable {

    loadProperties();

    // LOG the exceptions
    logger.error("Exception  : " + r.getMessage());
    logger.error(r);

    if (logger.isDebugEnabled()) {
        // Logging complete stacktrace in better format
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        r.printStackTrace(pw);
        logger.debug((sw.toString()));
    }
    // sendMail();

    if (r instanceof ProcessingException) {

        throw new OutputException(prop.getProperty("ER004"), r);
    } else if (r instanceof SystemException) {
        throw new OutputException(Error.DATABASE.toString(), r);
    }

}

public void loadProperties() {

    // use try with resource
    try {

        // load a properties file
        input = getClass().getClassLoader().getResourceAsStream("ErrorCodes.properties");
        prop.load(input);

    } catch (IOException ex) {
        ex.printStackTrace();
    } finally {
        if (input != null) {
            try {
                input.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

======================== 主要方法:

public class App {
public static void main(String[] args) {
    ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    SimpleService simpleService = (SimpleService) context.getBean("simpleServiceProxy");
    SecondService secondService = (SecondService) context.getBean("secondServiceProxy");
    // simple call to demo entry and exit logging to the methods of the
    // class
    simpleService.simpleCall();
    secondService.test2();
    try {
        // processing logic where exception is generated and handled
        simpleService.processingOperator();
    } catch (Exception e) {

        System.out.println(e);
        // TODO
        // Handle exception
    }

    // test the service on a different bean
    secondService.test3();
    context.close();
}

}

最佳答案

您可以使用 Spring 的组件扫描来 Autowiring 您的 bean。

只需添加

<context:component-scan base-package="<PACKAGE>" />

到您的applicationContext.xml。您必须将“”替换为您想要扫描 Bean 的包。

另外,你必须用注释你的bean

@Component

对 Spring 说“嘿,这是一个 bean”。要将依赖项注入(inject)其他 bean,只需使用

标记该字段即可
@Autowired

它们将被注入(inject)。

我希望这会有所帮助:)。

~法比安


编辑:如何使用 spring-aop 和 AspectJ。

您必须添加

<aop:aspectj-autoproxy />

到您的applicationContext.xml。然后,您必须定义一个包含您的方面的类。这个类是一个基本的Spring bean,注释为

@Component

然后您必须定义要通过切入点执行日志记录的连接点。

示例:

@Around("execution(* <BASE_PACKAGE>..*.* (..))")
public Object logAll(PreecedingJoinPoint joinPoint) throws Throwable {
    Object result = null;
    Throwable throwable = null;

    final StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    try {
        result = joinPoint.proceed();
    } catch (Throwable t) {
        throwable = t;
    }
    stopWatch.stop();

    if (throwable == null) {
        LOGGER.debug("Executed " + joinPoint.getSignature() + " in " + stopWatch.getTime() + "ms!");
    } else {
        LOGGER.debug("Executed " + joinPoint.getSignature() + " in " + stopWatch.getTime() + "ms! Threw an exception: " + throwable);
        throw throwable;
    }
    return result;
}

您可以通过 joinPoint.proceed() 继续执行。返回结果很重要!否则,每个方法都将返回 null!另外,抛出的异常必须抛出,否则会被抑制。

关于java - 使用方面记录 java 中方法的进入、退出和异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33445269/

相关文章:

java - 颜色 Libgdx 矩形对象

java - Spring mvc @RequestBody 字符串格式

Java Joda时间isAfter日期解决方案

java - 没有 XML 的引导 Spring Data JPA

java.lang.VerifyError : Stack map does not match the one at exception handle

java - Spring-boot - 每个级别的日志文件的应用程序属性配置

python - 日志记录与 print() + 日志记录最佳实践的优势

delphi - FastMM4,如何读取日志文件?

java - 使用线程开发基于 Java 的聊天应用程序

java - 如何让 Axis 1.4 不为同一个 XML namespace 生成多个前缀?