Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using java annotation to inject logger dependency

I am using spring with aspect-j annotation support to allow for an @Loggable annotation. This allows automatic logging on a class based on the configuration.

I am wondering if I can somehow use this annotation to expose an slf4j Logger variable into the class for direct use, so that I don't have to do something to the effect of:

Logger logger = LoggerFactory.getLogger(MyClass.class); 

It would be nice if the above was implicitly available due to the annotation and I could just go about doing logger.debug("..."); without the declaration. I'm not sure if this is even possible.

like image 914
mlo Avatar asked Jun 14 '11 22:06

mlo


People also ask

Which annotation is used to inject dependencies?

Dependency injection is simply an easier-to-program alternative to using the javax interfaces or JNDI APIs to look up resources. A field or a method of an application component can be annotated with the @Resource annotation.

What is @module annotation in Java?

The annotation @Module applies to the classes that contain behavior on how to construct the objects that users want to inject. The methods annotated by the @Provides annotation is the key to create the instances for injection. It returns the object you want to inject into other components.

What is @inject annotation in Java?

A method annotated with @Inject that overrides another method annotated with @Inject will only be injected once per injection request per instance. A method with no @Inject annotation that overrides a method annotated with @Inject will not be injected. Injection of members annotated with @Inject is required.

What is Java annotation used for?

Java annotations are metadata (data about data) for our program source code. They provide additional information about the program to the compiler but are not part of the program itself. These annotations do not affect the execution of the compiled program.


1 Answers

You can use the BeanPostProcessor interface, which is called by the ApplicationContext for all created beans, so you have the chance to fill the appropriate properties.

I created a simple implementation, which does that:

import java.lang.reflect.Field; import java.util.List;  import net.vidageek.mirror.dsl.Mirror;  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;  @Component public class LoggerPostProcessor implements BeanPostProcessor {      @Override     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {         List<Field> fields = new Mirror().on(bean.getClass()).reflectAll().fields();          for (Field field : fields) {             if (Logger.class.isAssignableFrom(field.getType()) && new Mirror().on(field).reflect().annotation(InjectLogger.class) != null) {                 new Mirror().on(bean).set().field(field).withValue(LoggerFactory.getLogger(bean.getClass()));             }         }         return bean;     }      @Override     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {         return bean;     } } 

You don't have to do any complex registration step, since the ApplicationContext is capable of recognizing BeanPostProcessor instances and automatically register them.

The @InjectLogger annotation is:

import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;  @Retention(RetentionPolicy.RUNTIME) public @interface InjectLogger { } 

And then you can easily use the annotation:

public static @InjectLogger Logger LOGGER;  ...  LOGGER.info("Testing message"); 

I used the Mirror library to find the annotated fields, but obviously you may perform a manual lookup in order to avoid this additional dependency.

It's actually a nice idea to avoid repeated code, and even small issues that come from copying and paste the Logger definitions from other classes, like when we forget to change the class parameter, which leads to wrong logs.

like image 55
Redder Avatar answered Sep 18 '22 05:09

Redder