3

我有一个使用 Spring 框架在 Java 1.5 中开发的 Web 应用程序。应用程序包含“仪表板”,它们是简单的页面,其中重新组合了一堆信息,用户可以在其中修改某些状态。经理希望我在数据库中为其中三个仪表板添加一个日志系统。每个仪表板都有不同的信息,但日志应按日期和用户登录进行跟踪。

我想做的是实现这样的策略模式:

interface DashboardLog {
   void createLog(String login, Date now);
}

// Implementation for one dashboard
class PrintDashboardLog implements DashboardLog {
  Integer docId;
  String status;

  void createLog(String login, Date now){
    // Some code
  }
}

class DashboardsManager {
  DashboardLog logger;
  String login;
  Date now;

  void createLog(){
     logger.log(login,now);
  }
}

class UpdateDocAction{
   DashboardsManager dbManager;

   void updateSomeField(){
      // Some action
      // Now it's time to log
      dbManagers.setLogger = new PrintDashboardLog(docId, status);
      dbManagers.createLog();
   } 
}

应用上下文.xml:

<bean id="dashboardManagers" class="...DashboardManagers" />

因此,在这个解决方案中,我没有使用依赖注入。这样做是“正确的”(良好的做法,表现,......)吗?有没有更好的方法可以使用 DI ?

注意:我没有编写诸如构造函数和 getter/setter 之类的基本内容。

4

3 回答 3

2

您的解决方案将为每次调用 updateSomeField() 创建一个新的 PrintDashboardLog 实例。这可能会占用不必要的时间/内存/GC 工作。此外,从设计的角度来看,如果每个 Dashboard 都有一个 DashboardLog,而不是每次调用都有一个新的 DashboardLog,这也是有意义的。

我认为使用 Logging 作为示例性用例之一的方面可能是一个好主意。就像是:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                            http://www.springframework.org/schema/aop
                            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <bean id="loggingAspect" class="com.yourcompany.yourapplication.aspects.DashboardLogAspect" />

    <aop:aspectj-autoproxy>
        <aop:include name="loggingAspect" />
    </aop:aspectj-autoproxy>

</beans>    


package com.yourcompany.yourapplication.aspects;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class DashboardLogAspect {

    @Around("execution(* com.yourcompany.yourapplication..*Action+.*(..)) && target(target)")
    public Object logActionCall(ProceedingJoinPoint pjp, Object target) throws Throwable {

        long before = System.nanoTime();

        Object returnValue = pjp.proceed();

        long after = System.nanoTime();
        long durationNs = after - before;

        String logMsg = target.getClass() + "." + pjp.getSignature().toShortString() + " (" + durationNs + " ns)";

        // TODO: store the log message in your database
        System.out.println(logMsg);

        return returnValue;
    }            
}

这会记录对名称以“Action”结尾的应用程序类的所有调用。它还增加了每次调用完成的时间。您可能还想针对特定的方法名称模式调整 Around 建议。请参阅AspectJ 编程指南

于 2010-12-29T12:16:44.600 回答
1

虽然像您一样使用策略模式是完全“正确的”,但考虑到您正在使用 Spring 的事实 -最好使用 Spring 框架提供的依赖注入机制 - 不妨使用什么您的框架必须提供作为其核心优势之一。

于 2010-12-29T10:53:06.327 回答
1

如果每个“仪表板”都有一个控制器,为什么不从控制器调用日志记录。


public interface DashboardLog
{
    void createLog(...);
}

public class DashboardUno
implements DashboardLog
{
    ...
    public void createLog(...)
    { ... }
}

@Controller
@RequestMapping("/blah/schmarr")
public class BlahController
{
    ...
    @RequestMapping(value = "/xxx")
    public String someMeaningfulName(...)
    {
        DashboardUno elEsUno;
        ... get the dashboard object ...
        elEsUno.createLog(...);
        ...
    }
}
于 2010-12-29T17:58:35.467 回答