参照别人的代码做了个Demo如下:
Spring的加载时自动自行此bean的应用
package cn.com.vnvtrip.spring.log4j.ext;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import cn.com.vnvtrip.spring.log4j.anonation.Logger;
/**
* Log4j日志注解化的应用 基本原理如下:
* 通过自定义一个BeanPostProcessor, 在对所有bean初始化之前,
* 对每一个bean的field进行检查, 是否适用了Logger注解, 如果有, 则调用LogFactory创建一个logger实例.
*
* @author longgangbai
*
*/
public class LogBeanPostProcessor implements BeanPostProcessor {
/**
* 初始化之后的操作
*/
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
/**
* 初始化之前的操作的处理
*/
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
List<Class<?>> clazzes = getAllClasses(bean);
for (Class<?> clazz : clazzes) {
initializeLog(bean, clazz);
}
return bean;
}
/**
* 初始化添加日志功能的
*
* @param bean
* @param clazz
*/
private void initializeLog(Object bean, Class<? extends Object> clazz) {
Field[] fiels = clazz.getDeclaredFields();
for (Field field : fiels) {
if (field.getAnnotation(Logger.class) == null) {
continue;
}
if (!field.getType().isAssignableFrom(Log.class)) {
continue;
}
// 獲取是否可以方法的属性
boolean visable = field.isAccessible();
try {
// 設置可以属性为可以访问
field.setAccessible(true);
field.set(bean, LogFactory.getLog(clazz));
} catch (Exception e) {
throw new BeanInitializationException(String.format(
"初始化logger失败!bean=%s;field=%s", bean, field));
} finally {
// 恢复原来的访问修饰
field.setAccessible(visable);
}
}
}
/**
*
* 獲取制定bean的class以及所有父类的列表,该列表中顺序为从父类中当前类
*
* @param bean
* @return
*/
private List<Class<?>> getAllClasses(Object bean) {
Class<? extends Object> clazz = bean.getClass();
List<Class<?>> clazzes = new ArrayList<Class<?>>();
while (clazz != null) {
clazzes.add(clazz);
clazz = clazz.getSuperclass();
}
Collections.reverse(clazzes);
return clazzes;
}
}
設置注解类
package cn.com.vnvtrip.spring.log4j.anonation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 添加一個日志注解类
*
* @author longgangbai
*
*/
@Retention(RetentionPolicy.RUNTIME) //运行是编译
@Target( { ElementType.FIELD }) //修饰的字段
public @interface Logger {
}
package cn.com.vnvtrip.spring.log4j.test;
import org.apache.commons.logging.Log;
import cn.com.vnvtrip.spring.log4j.anonation.Logger;
public class LoggAnonation {
@Logger
private static Log log;
public double divide(int a, int b) {
if (b == 0) {
log.error("被除数不可以为0");
} else {
return a / b;
}
return -1;
}
}
Spring配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="logBeanPocessor"
class="cn.com.vnvtrip.spring.log4j.ext.LogBeanPostProcessor" />
<bean id="loganonation" class="cn.com.vnvtrip.spring.log4j.test.LoggAnonation"/>
</beans>
测试类:
package cn.com.vnvtrip.spring.log4j.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class LogTest {
public static void main(String[] args) {
ApplicationContext ctxapp = new ClassPathXmlApplicationContext(
"applicationContext.xml");
LoggAnonation logtest = (LoggAnonation) ctxapp.getBean("loganonation");
double a = logtest.divide(8, 0);
System.out.println(a);
}
}