场景:
Log Wrapper:slf4j,编码中每个类都需要通过
private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandler.class);
这种非智能的硬编码方式来生成logger实例.
优化:
在spring框架中,每个类实例化的是由spring ioc完成的.实现BeanPostProcessor接口 能够在实例初始化完成后做一些自定义的逻辑。
spring基于Annotation的初始化类就是实现了BeanPostProcessor接口。例如:@Required && RequiredAnnotationBeanPostProcessor。
故使用如下方式自动化初始Logger实例-基于spring 2.5-3.x:
1、定义Annotation:
/**
* Log Annotation for Logger Injection
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface Log {
String value() default "";
}
2、在目标类定义:
@Component
public class LoggerDemo{
@Log
private Logger logger;
//some methods
//some properties
}
3、自定义BeanPostProcessor
/**
* init the slf4j logger in each spring bean
*/
@Component
public class LoggerBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(),new FieldCallback() { // spring reflection utils
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (field.getType().equals(Logger.class) && field.isAnnotationPresent(Log.class)) {//Log Annotation check
Log logAnnotation = field.getAnnotation(Log.class);
String loggerName = logAnnotation.value();
Logger logger = null;
if (loggerName != null && !loggerName.equals("")) {
logger = LoggerFactory.getLogger(loggerName);
}else {
logger = LoggerFactory.getLogger(bean.getClass());
}
field.set(bean, logger);// init value
}
}
});
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}