3

Spring フレームワークを使用して Java 1.5 で開発された Web アプリケーションがあります。アプリケーションには「ダッシュボード」が含まれています。これは、一連の情報が再グループ化され、ユーザーがステータスを変更できる単純なページです。マネージャーは、これらのダッシュボードのうち 3 つのデータベースにログ システムを追加するように求めています。各ダッシュボードには異なる情報がありますが、ログは日付とユーザーのログインによって追跡する必要があります。

私がやりたいのは、次のような戦略パターンを実装することです:

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

Appcontext.xml :

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

したがって、このソリューションでは、依存性注入を使用していません。このようにするのは「正しい」(良い習慣、パフォーマンスなど)ですか?DI を使用できるより良い方法はありますか?

注:コンストラクターやゲッター/セッターなどの基本的なものは書きませんでした。

4

3 に答える 3

2

ソリューションは、updateSomeField() への呼び出しごとに PrintDashboardLog の新しいインスタンスを作成します。これは、不必要な時間/メモリ/GC の労力を消費する可能性があります。また、設計の観点からは、呼び出しごとに 1 つの新しい DashboardLog ではなく、Dashboard ごとに 1 つの DashboardLog があることが理にかなっています。

ロギングが典型的なユースケースの 1 つである側面を使用することは良い考えかもしれないと思います。何かのようなもの:

<?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

各「ダッシュボード」にコントローラーがある場合は、コントローラーからロギングを呼び出してみませんか。


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 に答える
1

あなたが持っているように戦略パターンを採用することは完全に「正しい」ですが、Springを使用しているという事実を考慮すると、Springフレームワークによって提供される依存性注入メカニズムを採用する方が良いでしょう-フレームワークは、そのコアの強みの 1 つとして提供する必要があります。

于 2010-12-29T10:53:06.327 に答える