The Spring Inject Logger using Annotation tutorial shows you how to inject a logger with custom annotation. This tutorial helps you inject a logger into anywhare you want it. You will get the benefits in the testing work and operating application.
Logger Dependencies
In this Spring Inject Logger using Annotation tutorial, we are using two dependencies: slf4j logger interface and log4j logger implementation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<!-- logging interface --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <!-- Binding for Log4J --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.version}</version> </dependency> <!-- Log4j API and Core implementation required for binding --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j.version}</version> </dependency> |
Notice: in the demo application, we will add the spring dependencies. You can see the detail in the complete source code.
Configure Spring with Java Annotation
We use Spring Java Configuration to configure our spring beans.
1 2 3 4 5 6 7 8 9 10 |
package com.javabycode; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages = "com.javabycode") public class MyApplicationConfig { } |
Create custom annotation
We will create a new @MyLogger annotation like below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.javabycode; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; @Retention(RUNTIME) @Target(FIELD) @Documented public @interface MyLogger { } |
Spring Inject Logger using Annotation
Now, we can use the @MyLogger annotation at field level to inject a Logger.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
package com.javabycode; import org.slf4j.Logger; import org.springframework.stereotype.Component; @Component public class HelloService { private static @MyLogger Logger myLogger; public void sayHello(String msg){ myLogger.info(msg); } } |
Create MyLoggerInjector
The above @MyLogger injection is only the declaration on a field that we want to inject a Logger bean on that field. Next, we have to initialize that bean while Spring initialize a bean for the parent class. To do that, we implement the BeanPostProcessor interface which gives us the postProcessBeforeInitialization to manage a bean before initialization. And we inject an implementation with the LoggerFactory manually by searching for the @MyLogger annotation and initialize that bean. The below is detail implemenation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com.javabycode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; @Component public class MyLoggerInjector implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessBeforeInitialization(final Object bean, String name) throws BeansException { ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() { public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { ReflectionUtils.makeAccessible(field);// make sure the field accessible if defined private if (field.getAnnotation(MyLogger.class) != null) { Logger log = LoggerFactory.getLogger(bean.getClass()); field.set(bean, log); } } }); return bean; } } |
Configure Log4j2 xml
Add the log4j2.xml with the below content to project classpath.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="UTF-8"?> <Configuration xmlns="http://logging.apache.org/log4j/2.0/config"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <PatternLayout pattern="%-5p | %d{yyyy-MM-dd HH:mm:ss} | [%t] %C{2} (%F:%L) - %m%n"/> </Console> </Appenders> <Loggers> <Logger name="com.javabycode" level="debug"/> <Root level="info"> <AppenderRef ref="STDOUT"/> </Root> </Loggers> </Configuration> |
Demo Application
In this Spring Inject Logger using Annotation, we create demo application to test what we share above. First we create main class to bootstrap spring configuration. Then we call the service.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.javabycode; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MyApplication { public static void main(String...args){ ApplicationContext context = new AnnotationConfigApplicationContext(MyApplicationConfig.class); HelloService helloService = context.getBean(HelloService.class); helloService.sayHello("Run 1"); helloService.sayHello("Run 2"); helloService.sayHello("Run 3"); } } |
Run the above main, the output will print the logging information:
1 2 3 |
INFO | 2017-03-22 14:07:44 | [main] javabycode.HelloService (HelloService.java:12) - Run 1 INFO | 2017-03-22 14:07:44 | [main] javabycode.HelloService (HelloService.java:12) - Run 2 INFO | 2017-03-22 14:07:44 | [main] javabycode.HelloService (HelloService.java:12) - Run 3 |
That’s all on the Spring Inject Logger using Annotation tutorial.
References
BeanPostProcessor JavaDoc
Download complete source code, click link below
spring-inject-logger-using-annotation.zip (276 downloads)