使用方面记录 Java 中方法的进入、退出和异常 [英] Logging entry, exit and exceptions for methods in java using aspects

查看:27
本文介绍了使用方面记录 Java 中方法的进入、退出和异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using the below code to log entry, exit and exceptions using aspects. This way I have to define a bean for every class in my application in my ApplicationContext and it becomes cumbersome to maintain such length of bean definitions and their properties. Can you help me simplify this? I don't think it is appropriate design to define bean everytime I create a class. Help is appreciated, thanks in advance.

<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 类:

==================== LogEntry class:

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 类:

========================= LogReturn class:

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());
}

==============================ExceptionLogger 类

============================== ExceptionLogger class

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();
            }
        }
    }

}

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

======================= Main method:

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 的组件扫描来自动装配您的 bean.

you can use Spring's component scan to autowire your beans.

只需添加

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

到您的 applicationContext.xml.您必须将 "" 替换为要扫描 bean 的包.

to your applicationContext.xml. You have to replace "" with the package you want to scan for beans.

另外,你必须用

@Component

对 Spring 说嘿,这是一个 bean".要将依赖项注入其他 bean,只需用

to say "hey, this is a bean" to Spring. To inject dependencies into other beans, simply tag the field with

@Autowired

它们将被注入.

我希望这会有所帮助:)

I hope this will help :).

~法比安

如何使用 spring-aop 和 AspectJ.

How to use spring-aop and AspectJ.

你必须添加

<aop:aspectj-autoproxy />

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

to your applicationContext.xml. Then, you have to define a class that will contain your aspects. This class is a basic Spring bean, annotated with

@Component

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

Then you have to define the join-points where you want to execute your logging via pointcuts.

示例:

@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!另外,必须抛出抛出的异常,否则会被抑制.

You continue the execution via joinPoint.proceed(). It is important that you return the result! Otherwise, every method will return null! Also, you must throw the thrown exception, otherwise it will be suppressed.

这篇关于使用方面记录 Java 中方法的进入、退出和异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆