Tutorial Mkyong ini menyarankan untuk menginternalkan penebang dengan cara ini:
@Controller
public class WelcomeController {
private static final Logger logger = Logger.getLogger(WelcomeController.class);
// etc
}
Sekarang mungkin setiap kelas lain yang Anda gunakan, yang memiliki logger akan menginisialisasi logger mereka dengan cara yang sama.
Pertanyaan saya adalah - apakah ini cara terbaik untuk melakukannya? Sepertinya ... berulang.
getLogger()
nama logger untuk mendapatkannya.Jawaban:
Komentar Anda mengatakan bahwa "verbose" mengacu pada kebutuhan untuk mengulangi baris kode ini di setiap kelas. Tanggapan pertama saya adalah bahwa, dalam gambar besar, menambahkan dua baris kode (definisi variabel ditambah pernyataan impor) untuk setiap kelas bukan masalah besar. Terutama karena Anda hanya perlu menambahkannya ke kelas yang memiliki perilaku dan karenanya perlu melakukan logging. Yang mengatakan, baris kode tertentu yang Anda gunakan cenderung untuk kesalahan copy-paste (lebih lanjut tentang itu nanti).
Tetapi, karena Anda menginginkan alternatif, berikut adalah beberapa, dengan alasan Anda mungkin atau mungkin tidak ingin menggunakannya.
Gunakan logger tunggal untuk seluruh aplikasi
Jika Anda tidak peduli tentang apa yang dilaporkan oleh kelas, atau bersedia untuk memasukkan semua konteks yang diperlukan ke dalam pesan, maka pekerjaan logger singleton sederhana akan berhasil:
Menurut pendapat saya, salah satu manfaat besar dari kerangka logging adalah memiliki konteks yang disediakan oleh instance logger terpisah - jika hanya untuk mengarahkan pesan log ke tujuan yang berbeda. Saya tidak akan menyerah hanya untuk menyimpan satu baris kode (Anda masih perlu impor).
Plus, ini meningkatkan verbositas pada titik penggunaan, yang akan berakhir dengan penekanan tombol yang jauh lebih banyak.
Buat penebang Anda pada titik penggunaan
Saya membuang yang satu ini hanya karena menghilangkan variabel. Saya rasa saya tidak perlu berkomentar tentang itu. Meskipun tidak menunjukkan teknik pilihan saya untuk mendapatkan contoh logger.
Gunakan post-prosesor kacang untuk menyuntikkan logger
Contoh Anda menggunakan Spring, dan Spring memungkinkan Anda menghubungkan ke kode inisialisasi kacang. Anda bisa membuat post-prosesor yang memeriksa kacang untuk
logger
variabel anggota, dan membuatLogger
contoh ketika menemukannya.Walaupun post-processor seperti itu hanya beberapa lusin baris kode, ini merupakan bagian yang bergerak dalam aplikasi Anda, dan karenanya berpotensi menjadi sumber bug. Saya lebih suka memiliki beberapa dari mereka mungkin.
Gunakan mixin
Scala dan Groovy memberikan ciri-ciri , yang memungkinkan Anda merangkum perilaku. Pola Scala yang khas adalah membuat
Logging
sifat, lalu menambahkannya ke kelas yang perlu dicatat:Sayangnya, ini berarti Anda harus beralih bahasa. Kecuali Anda menggunakan Java 8, dalam hal ini Anda dapat membuat
Logging
antarmuka dengan "metode default":Sekarang, dalam kode kelas Anda, Anda dapat menggunakannya
Meskipun mudah, ini memiliki beberapa kelemahan. Untuk satu hal, itu mencemari antarmuka setiap kelas yang menggunakannya, karena semua metode antarmuka bersifat publik. Mungkin tidak terlalu buruk jika Anda menggunakannya hanya untuk kelas yang dipakai dan disuntikkan oleh Spring, terutama jika Anda mengikuti pemisahan antarmuka / implementasi.
Masalah yang lebih besar adalah bahwa ia harus mencari contoh logger yang sebenarnya pada setiap panggilan. Yang cepat, tetapi tidak perlu.
Dan Anda masih membutuhkan pernyataan impor.
Pindahkan logger ke superclass
Saya akan ulangi: Saya tidak menemukan definisi logger berulang-ulang, tetapi jika Anda melakukannya, saya pikir ini pendekatan terbaik untuk menghilangkannya.
Sekarang kelas pengontrol Anda mewarisi dari
AbstractController
, dan mereka memiliki akses kelogger
variabel. Ingatlah bahwa Anda harus meletakkan@Controller
anotasi di kelas yang konkret.Beberapa orang akan menemukan ini penyimpangan warisan. Saya telah mencoba meredakan mereka dengan memberi nama kelas
AbstractController
daripadaAbstractProjectClass
. Anda dapat memutuskan sendiri apakah ada hubungan is-a .Orang lain akan keberatan dengan penggunaan variabel instan daripada variabel statis. Logger statis IMO rentan terhadap kesalahan salin-tempel, karena Anda harus secara eksplisit merujuk nama kelas;
getClass()
memastikan bahwa logger Anda selalu benar.sumber
MethodHandles.lookup().lookupClass()
lebih baik daripadaObject.getClass()
?MethodHandles.lookup().lookupClass()
dapat digunakan untuk variabel statis, tidak rentan terhadap kesalahan salin-tempel dan cepat: stackoverflow.com/a/47112323/898747 Itu berarti inport tambahan, tetapi saya cukup suka logger saya menjadi statis sehingga setidaknya layak sebutkan :)Untuk memperluas jawaban yang diberikan oleh @kdgregory, Groovy menyediakan
@Slf4j
(groovy.util.logging.Slf4j
) di luar kotak sebagai anotasi yang melakukan transformasi AST pada kelas untuk menangani dengan logger yang mengasumsikan nama variabellog
secara default jika dibiarkan tidak ditentukan.sumber