Ce didacticiel Mkyong propose d'intialiser les enregistreurs de cette façon:
@Controller
public class WelcomeController {
private static final Logger logger = Logger.getLogger(WelcomeController.class);
// etc
}
Maintenant, probablement toutes les autres classes que vous utilisez, qui ont un enregistreur initialiseront leurs enregistreurs de la même manière.
Ma question est - est-ce la meilleure façon de le faire? Cela semble ... répétitif.
getLogger()
le nom de l'enregistreur à obtenir.Réponses:
Votre commentaire dit que "verbeux" fait référence à la nécessité de répéter cette ligne de code dans chaque classe. Ma première réponse est que, dans l'ensemble, l'ajout de deux lignes de code (définition de variable plus déclaration d'importation) à chaque classe n'est pas si grave. D'autant plus que vous avez seulement besoin de les ajouter aux classes qui ont un comportement et doivent donc faire la journalisation. Cela dit, la ligne de code spécifique que vous utilisez est sujette à des erreurs de copier-coller (plus d'informations à ce sujet plus tard).
Mais, puisque vous voulez des alternatives, voici quelques-unes, avec des raisons pour lesquelles vous pourriez ou non vouloir les utiliser.
Utilisez un seul enregistreur pour toute l'application
Si vous ne vous souciez pas de la classe qui rapporte, ou si vous êtes prêt à mettre tout le contexte nécessaire dans le message, un simple enregistreur singleton fera le travail:
À mon avis, l'un des grands avantages d'un cadre de journalisation est que le contexte est fourni par des instances d'enregistreur distinctes - ne serait-ce que pour diriger les messages de journal vers différentes destinations. Je n'abandonnerais pas cela juste pour enregistrer une ligne de code (vous avez toujours besoin de l'importation).
De plus, cela augmente la verbosité au point d'utilisation, ce qui se traduira par beaucoup plus de frappes.
Créez vos enregistreurs au point d'utilisation
Je jette celui-ci juste parce qu'il élimine la variable. Je ne pense pas avoir besoin de commenter cela. Bien qu'il montre ma technique préférée pour obtenir une instance d'enregistreur.
Utilisez un post-processeur de bean pour injecter l'enregistreur
Votre exemple utilise Spring et Spring vous permet de vous connecter au code d'initialisation du bean. Vous pouvez créer un post-processeur qui inspecte le bean pour une
logger
variable membre et crée uneLogger
instance lorsqu'il en trouve une.Bien qu'un tel post-processeur ne représente que quelques dizaines de lignes de code, c'est une autre partie mobile de votre application, et donc une autre source potentielle de bogues. Je préfère en avoir le moins possible.
Utilisez un mixin
Scala et Groovy fournissent des traits qui vous permettent d'encapsuler le comportement. Un modèle Scala typique consiste à créer un
Logging
trait, puis à l'ajouter à la classe qui doit être journalisée:Malheureusement, cela signifie que vous devez changer de langue. Sauf si vous utilisez Java 8, auquel cas vous pouvez créer une
Logging
interface avec une "méthode par défaut":Maintenant, dans votre code de classe, vous pouvez simplement utiliser
Bien que facile, cela présente quelques inconvénients. D'une part, il pollue l'interface de chaque classe qui l'utilise, car toutes les méthodes d'interface sont publiques. Peut-être pas si mal si vous ne l'utilisez que pour des classes instanciées et injectées par Spring, surtout si vous suivez la séparation interface / implémentation.
Le plus gros problème est qu'il doit rechercher l'instance réelle de l'enregistreur à chaque appel. Ce qui est rapide, mais inutile.
Et vous avez toujours besoin d'une déclaration d'importation.
Déplacer l'enregistreur vers une superclasse
Je répète: je ne trouve pas verbeux les définitions d'enregistreurs répétées, mais si vous le faites, je pense que c'est la meilleure approche pour les éliminer.
Maintenant, vos classes de contrôleurs héritent de
AbstractController
et ont accès à lalogger
variable. N'oubliez pas que vous devez mettre l'@Controller
annotation sur la classe concrète.Certaines personnes trouveront cela une perversion de l'héritage. J'ai essayé de les apaiser en nommant la classe
AbstractController
plutôt queAbstractProjectClass
. Vous pouvez décider vous-même s'il existe ou non une relation est-une .D'autres personnes s'opposeront à l'utilisation d'une variable d'instance plutôt que d'une variable statique. Les enregistreurs statiques IMO sont sujets à des erreurs de copier-coller, car vous devez référencer explicitement le nom de classe;
getClass()
s'assure que votre enregistreur est toujours correct.la source
MethodHandles.lookup().lookupClass()
est meilleure queObject.getClass()
?MethodHandles.lookup().lookupClass()
peut être utilisé pour les variables statiques, n'est pas sujet aux erreurs de copier-coller et est rapide: stackoverflow.com/a/47112323/898747 Cela signifie un inport supplémentaire, mais j'aime beaucoup mes enregistreurs statiques, donc cela vaut au moins la peine mention :)Pour étendre la réponse fournie par @kdgregory, Groovy fournit
@Slf4j
(groovy.util.logging.Slf4j
) hors de la boîte comme une annotation qui effectue une transformation AST sur la classe pour la clouer avec un enregistreur qui assume le nom de variablelog
par défaut s'il n'est pas spécifié.la source