有没有一种简单的方法可以为每个类创建一个记录器实例?

Jas*_*key 5 java logging spring dependency-injection log4j

我现在用的是静态方式来记录(因为我觉得在Android中登录非常容易),但是现在我需要为不同的类配置不同的appender,所以静态记录方式有问题。

我阅读了Log4J: Strategies for create Logger instances,我注意到是时候更改日志记录策略了,所以我需要将以下代码添加到需要特殊记录器的类中。

private static final Logger logger  =  Logger.getLogger(XXXX.class);
Run Code Online (Sandbox Code Playgroud)

我觉得既然这是重复的工作,那么我们有什么方法可以避免在每个类中添加重复的代码,或者只是少写一些代码。AOP 或依赖注入可以做这样的工作吗?

我正在使用 log4j 和 Spring,但任何其他方法都将受到高度赞赏。

SMA*_*SMA 2

是的,你可以。

  • 创建您的自定义注释,比如@Logger

    @Retention(RUNTIME)//will be used at runtime, so retain till runtime
    @Target(FIELD)//field level annotation
    public @interface Logger {
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在 Spring 注入的 bean 中将 Logger 字段注释为 @Logger。

    @Logger
    private Logger logger;
    
    Run Code Online (Sandbox Code Playgroud)

    在这里您可以使用 slf4j 记录器,但由您决定,因为您可以直接使用 log4j 等。请参阅我如何在这里注释记录器。这是由 Spring 创建的 bean 内的。

  • 使用名为 BeanPostProcessor 的 Spring 生命周期接口,并在方法 postProcessBeforeInitialization 中,使用反射 utils 类来注入记录器。

    public class LoggerInjector implements BeanPostProcessor {
    
    /**
     * Return the bean itself.
    */
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        return bean;
    }
    
    /**
     * For all beans before initialization, inject the logger using slf4j.
     * @param bean
     * @param beanName
     * @return returns same bean by injecting logger.
     */
    public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
        ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
            public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException {
                ReflectionUtils.makeAccessible(field);
                if (field.getAnnotation(Logger.class) != null) {
                    if (field.get(bean) == null) {
                        final Logger logger = LoggerFactory.getLogger(bean.getClass());
                        field.set(bean, logger);
                    }
                }
            }
        });
        return bean;
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 完成后,让 spring 知道您有一个记录器注入器,例如:

    <bean id="loggerInjector" 
        class="com.mypackage.LoggerInjector"/>
    
    Run Code Online (Sandbox Code Playgroud)