问题描述
陷入了怪异的要求.我需要将唯一的错误ID连接到Log4J消息,然后将该消息ID返回接口.
public class LoggingService { protected static Logger logger = LoggerFactory.getLogger(LoggingService.class); public String debug(String debug_msg) { String uniqueMsgId = generateUniqueId(); logger.debug(concatIdWithMsg(uniqueMsgId, debug_msg)); return uniqueMsgId; } }
并将其自动到我需要的任何地方.
public class LoginLogoutController { @Autowired LoggingService logger; @RequestMapping(value = "/login", method = RequestMethod.GET) public String getLoginPage() { logger.debug("Login page requested"); } }
尽管效果很好,但是Logger MSG中的源类是LoggingService,这很明显.我想要的是通过自动loggingservice的类,以便记录器消息显示问题的原始来源.我尝试以某种方式更改服务 但没有进一步的想法如何通过源类
public class LoggingService<T> { protected static Logger logger = null; Class<T> sourceClass; public void construct(Class<T> sourceClass) { this.sourceClass = sourceClass; logger = LoggerFactory.getLogger(sourceClass); } public String debug(String debug_msg) { String uniqueMsgId = generateUniqueId(); logger.debug(concatIdWithMsg(uniqueMsgId, debug_msg)); return null; } }
推荐答案
我使用这种机制注入了一个记录器.
创建此注释..
/** * Indicates InjectLogger of appropriate type to * be supplied at runtime to the annotated field. * * The injected logger is an appropriate implementation * of org.slf4j.Logger. */ 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 InjectLogger { }
现在,让我们定义一个实际完成注射记录器实现的工作的类.
/** * Auto injects the underlying implementation of logger into the bean with field * having annotation <code>InjectLogger</code>. * */ import java.lang.reflect.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.util.ReflectionUtils; import static org.springframework.util.ReflectionUtils.FieldCallback; public class LoggerInjector implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() { public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { // make the field accessible if defined private ReflectionUtils.makeAccessible(field); if (field.getAnnotation(InjectLogger.class) != null) { Logger log = LoggerFactory.getLogger(bean.getClass()); field.set(bean, log); } } }); return bean; } }
使用它甚至更简单.只需将上面创建的记录器注释添加到所需类中的日志字段中即可.
import org.slf4j.Logger; public class Demo { @InjectLogger private Logger log; public void doSomething() { log.info("message"); log.error("Lets see how the error message looks..."); } }
其他推荐答案
为什么不使用Spring AOP. AOP为您提供了很多可访问性和功能,当您的应用程序变得沉重时,您以后还可以利用其有趣的功能.
问题描述
Caught up in a weird requirement. I need to attach unique error id to log4j message and return that message id back to interface.So, I though lets create a spring service, like this
public class LoggingService { protected static Logger logger = LoggerFactory.getLogger(LoggingService.class); public String debug(String debug_msg) { String uniqueMsgId = generateUniqueId(); logger.debug(concatIdWithMsg(uniqueMsgId, debug_msg)); return uniqueMsgId; } }
and autowired this to wherever i need it.
public class LoginLogoutController { @Autowired LoggingService logger; @RequestMapping(value = "/login", method = RequestMethod.GET) public String getLoginPage() { logger.debug("Login page requested"); } }
Although it worked fine, but the source class in logger msg is LoggingService which is obvious. What i want is to pass the class in which LoggingService is autowired so that the logger message shows the original source of problem. I tried somehow to change the service but got no further idea how to pass source class
public class LoggingService<T> { protected static Logger logger = null; Class<T> sourceClass; public void construct(Class<T> sourceClass) { this.sourceClass = sourceClass; logger = LoggerFactory.getLogger(sourceClass); } public String debug(String debug_msg) { String uniqueMsgId = generateUniqueId(); logger.debug(concatIdWithMsg(uniqueMsgId, debug_msg)); return null; } }
推荐答案
I used this mechanism to inject a logger.
Create this annotation..
/** * Indicates InjectLogger of appropriate type to * be supplied at runtime to the annotated field. * * The injected logger is an appropriate implementation * of org.slf4j.Logger. */ 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 InjectLogger { }
Now lets define a class that actually does the job of injecting the logger implementation.
/** * Auto injects the underlying implementation of logger into the bean with field * having annotation <code>InjectLogger</code>. * */ import java.lang.reflect.Field; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.util.ReflectionUtils; import static org.springframework.util.ReflectionUtils.FieldCallback; public class LoggerInjector implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException { ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() { public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { // make the field accessible if defined private ReflectionUtils.makeAccessible(field); if (field.getAnnotation(InjectLogger.class) != null) { Logger log = LoggerFactory.getLogger(bean.getClass()); field.set(bean, log); } } }); return bean; } }
Using it is even simpler. Just add the Logger annotation created above to the Log field in the required class.
import org.slf4j.Logger; public class Demo { @InjectLogger private Logger log; public void doSomething() { log.info("message"); log.error("Lets see how the error message looks..."); } }
其他推荐答案
Why dont you use Spring AOP. AOP provides you much accessibility and features, and you can exploit its interesting features later also, when your application becomes heavy. Spring AOP