Spring:Spring中可以访问私有创建的对象吗?

时间:2012-10-18 09:27:59

标签: java spring spring-aop

我有一个Java类,如下所示:

public class Foo{
   public void doSomething(){
     StageA a = new StageA();
     StageB b = new StageB();
     StageC c = new StageC();
     a.execute();
     b.execute();
     c.execute();
   }
}

现在,假设我无法真正编辑此类本身,我仍然可以使用 spring AOP 来应用around execute方法的日志记录吗? (大概不使用 aspect4j

3 个答案:

答案 0 :(得分:2)

那么你可以记录方法和它所需的时间(性能),但我认为你不能记录正在做什么方法。

来自Spring Docs

  

围绕建议:围绕连接点的建议,例如方法调用。这是最有力的建议。 around通知可以在方法调用之前和之后执行自定义行为。它还负责选择是继续加入点还是通过返回自己的返回值或抛出异常来快速建议的方法执行。


如果您在方法内部使用log4j记录器,则可以通过配置log4j来记录正在执行的操作。

  

(大概不使用aspect4j)

- > Spring内部使用aspectJ

检查here以获取参考和示例

答案 1 :(得分:2)

<强>编辑: 我不认为可以在你的情况下记录每个“execute”方法的执行而不改变Foo或Stage类。因为Stage ...类不是由容器管理的。只能在doSomething方法开始执行时记录(如果Foo类由Spring容器管理),则无法控制它的执行流程。

如果您的类要由Spring容器管理,那么您可以轻松完成此操作。你应该简单地为Stage ...类编写Spring AOP“around”方面,而不是为Foo类编写。

以下是简单日志记录方面的示例:

@Component
@Aspect
@Order(value=2)
public class LoggingAspect {

    @Around("execution(* com.blablabla.server..*.*(..))")
    public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable{
        final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass().getName());
        Object retVal = null;

        try {
            StringBuffer startMessageStringBuffer = new StringBuffer();

            startMessageStringBuffer.append("Start method ");
            startMessageStringBuffer.append(joinPoint.getSignature().getName());
            startMessageStringBuffer.append("(");

            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                startMessageStringBuffer.append(args[i]).append(",");
            }
            if (args.length > 0) {
                startMessageStringBuffer.deleteCharAt(startMessageStringBuffer.length() - 1);
            }

            startMessageStringBuffer.append(")");

            logger.trace(startMessageStringBuffer.toString());

            StopWatch stopWatch = new StopWatch();
            stopWatch.start();

            retVal = joinPoint.proceed();

            stopWatch.stop();

            StringBuffer endMessageStringBuffer = new StringBuffer();
            endMessageStringBuffer.append("Finish method ");
            endMessageStringBuffer.append(joinPoint.getSignature().getName());
            endMessageStringBuffer.append("(..); execution time: ");
            endMessageStringBuffer.append(stopWatch.getTotalTimeMillis());
            endMessageStringBuffer.append(" ms;");

            logger.trace(endMessageStringBuffer.toString());
        } catch (Throwable ex) {
            StringBuffer errorMessageStringBuffer = new StringBuffer();

             // Create error message 
             logger.error(errorMessageStringBuffer.toString(), e)

            throw ex;
        }

        return retVal;
    }
}

答案 2 :(得分:1)

是的,您可以使用@Around切入点定位名称为execution的方法撰写execute()个建议,如下所示:

@Around("execution(* execute(..))")
public Object execute(ProceedingJoinPoint pjp) throws Throwable
{
    // Log statements before the call;

    Object obj = pjp.proceed();

    // Log statements after the call;

    return obj;
}