Javaリードソースデザインモード:アダプタアダプタアダプタアダプタアダプタ


アダプタモード関連ソース:slf 4 j-1.6.1、hibernate-3.6.7
log 4 jは広く使われているログツールであることはよく知られていますが、sun社にはJDKにも独自のログツール、java.util.logging.Loggerがあります.もちろん他にもログツールがあります.
さまざまなログツールの機能と使用方法は似ていますが、一般的にはdebug、info、warn、errorなどのログレベルの方法が含まれていますが、共通のインタフェースは実現されていません.この点はJDBCとは異なり、MySQL、Oracleなど、リレーショナル・データベースの種類は多いが、統合されたインタフェース、すなわちJDBCがある.
もちろん、自分でプロジェクトを書くなら、勝手にログツールを探して使えばいいです.しかし、一部のオープンソースフレームワークの著者は、あなたのシステムがどのログツールを使用しているのか、オープンソースフレームワークでどのログツールを使用しているのか分からないことに悩んでいます.
slf 4 jは共通のインタフェースを提供し、異なるログツールのアダプタを実現しています.したがって、オープンソースフレームワークでは、slf 4 jが提供するインタフェースを呼び出すだけで、どの実装クラスを使用するかに関心を持つ必要はありません.例えばORMフレームワークHibernateのログはslf 4 jに依存する.
slf 4 jと似ているのはcommons-loggingなどです.
ソース:
slf 4 jは、クライアント(例えばHibernate)に呼び出すために提供される統合インタフェースorg.slf 4 j.Loggerを提供する.
package org.slf4j;

public interface Logger {

  public boolean isTraceEnabled();

  public void trace(String msg);

  public void trace(String format, Object arg);

  public void trace(String format, Object arg1, Object arg2);

  public void trace(String format, Object[] argArray);

  public void trace(String msg, Throwable t);

  public boolean isDebugEnabled();

  public void debug(String msg);

  public void debug(String format, Object arg);

  public void debug(String format, Object arg1, Object arg2);

  public void debug(String format, Object[] argArray);

  public void debug(String msg, Throwable t);

  public boolean isInfoEnabled();

  public void info(String msg);

  public void info(String format, Object arg);

  public void info(String format, Object arg1, Object arg2);

  public void info(String format, Object[] argArray);

  public void info(String msg, Throwable t);

  public boolean isWarnEnabled();

  public void warn(String msg);

  public void warn(String format, Object arg);

  public void warn(String format, Object[] argArray);

  public void warn(String format, Object arg1, Object arg2);

  public void warn(String msg, Throwable t);

  public boolean isErrorEnabled();

  public void error(String msg);

  public void error(String format, Object arg);

  public void error(String format, Object arg1, Object arg2);

  public void error(String format, Object[] argArray);

  public void error(String msg, Throwable t);

}
クライアントhibernateではlog 4 jまたはJDK loggerを直接呼び出すのではなくorg.slf 4 j.Loggerインタフェースを使用します.hibernateにログがあるコードを選択します.
(注:LoggerFactory.getLoggerがどのように実現するかは注目する必要はありません)
package org.hibernate.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class SessionFactoryImpl implements SessionFactory, SessionFactoryImplementor {

	private static final Logger log = LoggerFactory.getLogger(SessionFactoryImpl.class);

	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
		log.trace("deserializing");
		in.defaultReadObject();
		log.debug("deserialized: " + uuid);
	}

	private void writeObject(ObjectOutputStream out) throws IOException {
		log.debug("serializing: " + uuid);
		out.defaultWriteObject();
		log.trace("serialized");
	}

}
log 4 jおよびJDKのloggerはslf 4 jのorg.slf 4 j.Loggerインタフェースを実現していないので、slf 4 jはorg.slf 4 j.Loggerインタフェースを実現するためにアダプタを提供し、アダプタからlog 4 jまたはJDKのloggerを呼び出してログを実現し、ログツールの互換性を実現する.(注:ソースコードでは、LocationAwareLoggerインタフェースがorg.slf 4 j.Loggerを継承していることがわかりますので、LocationAwareLoggerを実現することはorg.slf 4 j.Loggerを実現することに相当します)
Log 4 jアダプタorg.slf 4 j.impl.Log 4 jLoggerAdapter:
package org.slf4j.impl;

import java.io.Serializable;

import org.apache.log4j.Level;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.helpers.FormattingTuple;
import org.slf4j.helpers.MessageFormatter;
import org.slf4j.spi.LocationAwareLogger;

public final class Log4jLoggerAdapter extends MarkerIgnoringBase implements
    LocationAwareLogger, Serializable {

  final transient org.apache.log4j.Logger logger;

  public boolean isDebugEnabled() {
    return logger.isDebugEnabled();
  }

  public void debug(String msg) {
    logger.log(FQCN, Level.DEBUG, msg, null);
  }

  public void debug(String format, Object arg) {
    if (logger.isDebugEnabled()) {
      FormattingTuple ft = MessageFormatter.format(format, arg);
      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
  }

  public void debug(String format, Object arg1, Object arg2) {
    if (logger.isDebugEnabled()) {
      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
  }

  public void debug(String format, Object[] argArray) {
    if (logger.isDebugEnabled()) {
      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
  }

  public void debug(String msg, Throwable t) {
    logger.log(FQCN, Level.DEBUG, msg, t);
  }

}
Jdk loggerアダプタorg.slf 4 j.impl.JDK 14 Logger Adapter:
package org.slf4j.impl;

import java.util.logging.Level;

import org.slf4j.Marker;
import org.slf4j.helpers.FormattingTuple;
import org.slf4j.helpers.MarkerIgnoringBase;
import org.slf4j.helpers.MessageFormatter;
import org.slf4j.spi.LocationAwareLogger;

public final class JDK14LoggerAdapter extends MarkerIgnoringBase implements
    LocationAwareLogger {

  final java.util.logging.Logger logger;

  public boolean isDebugEnabled() {
    return logger.isLoggable(Level.FINE);
  }

  public void debug(String msg) {
    if (logger.isLoggable(Level.FINE)) {
      log(SELF, Level.FINE, msg, null);
    }
  }

  public void debug(String format, Object arg) {
    if (logger.isLoggable(Level.FINE)) {
      FormattingTuple ft = MessageFormatter.format(format, arg);
      log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
    }
  }

  public void debug(String format, Object arg1, Object arg2) {
    if (logger.isLoggable(Level.FINE)) {
      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
      log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
    }
  }

  public void debug(String format, Object[] argArray) {
    if (logger.isLoggable(Level.FINE)) {
      FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
      log(SELF, Level.FINE, ft.getMessage(), ft.getThrowable());
    }
  }

  public void debug(String msg, Throwable t) {
    if (logger.isLoggable(Level.FINE)) {
      log(SELF, Level.FINE, msg, t);
    }
  }

}
アダプタ・モードには、一般的に次のセクションがあります.
Adaptee:機能を実装する実装クラスですが、クライアントとは互換性がありません.つまり、上記のコードのjava.util.logging.Logger、org.apache.log 4 j.Loggerです.
Target:クライアントに呼び出されたインタフェースで、アダプタはこのインタフェースを実現します.上のコードのorg.slf 4 j.Loggerです.
Adapter:アダプタ、アダプタはTargetインタフェースを実現し、具体的な機能はAdapteeを呼び出して実現する.上のorg.slf 4 j.impl.Log 4 jLoggerAdapter、org.slf 4 j.impl.JDK 14 LoggerAdapterです.
Client:Targetインタフェースを呼び出します.上のHibernateです.
まとめ:
Java.util.logging.Logger、org.apache.log 4 j.Loggerなど、似たようなクラスが複数あり、統一されたインタフェースはありませんが、クライアントは互換性を望んでいます.このような場合、最善の方法は、同じインタフェースを実現させることです.しかし、再構築コストが大きすぎたり、同じインタフェースが実現できなかったり(例えば、上記の例ではlog 4 jとJDK loggerはまったく同じではない)、統合されたインタフェース(すなわちorg.slf 4 j.Logger)を作成し、クラスごとにアダプタ(すなわちorg.slf 4 j.impl.Logg 4 jLoggerAdapter、org.slf 4 j.impl.JDK 14 LoggerAdapter)を書く必要があります.アダプタに統合インタフェースを実装させ、具体的な実装クラスを呼び出して実装させ、互換性を達成しました.
フォークリフト  転載は出典を明記してください.http://blog.csdn.net/xiao__gui/article/details/32695647