面向切面记录log4j日志

12/12/2015来源:Java教程人气:1452

首先,AOP处理日志是必需的,不使用AOP处理日志有诸多不便。

日志处理是每个项目当中一个非常重要的内容。没有了日志,也就失去了对系统的可控性。没有日志,系统出现任何问题,都会没有踪迹可寻,这对一个信息系统而言是非常危险的。 

然而,使用纯OOP思想进行日志处理,我们会发现,每个逻辑部分中总会混入日志处理的代码,导致纯OOP思想的设计略显不伦不类。同时,如果记录日志的类型需求有变更,那么我们就要去每个逻辑单元中修改java代码。另外,如果需求今天变了明天再变的话,我想这将是一个非常繁重并且惹人厌的工作。

其实日志处理应该是软件系统中单独的一大部分,开发人员在进行系统开发时,不应该再来考虑日志处理。AOP能够做到这一点,让开发人员更加专注于系统的业务编码,而无需顾虑日志问题(这一点大家可以联系声明式事务处理的方式,配置好了处理事务的配置文件,编写Manager或者action时,都无需顾虑事务)。

然后,介绍例子中的代码实现。

1、引入jar包:

                 

2、切面aspect代码:

package com.lzq.sPRing.aop;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import com.lzq.spring.test.AOPTest;
/**
 * 切面
 * @author lzq
 *
 */
public class Aspect {
  
  Logger logger = Logger.getLogger(AOPTest.class);
  String strLog = null ;
  
  /**
   * 前置通知:在某连接点之前执行的通知,但这个通知不能阻止连接点前的执行
   * @param jp 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
   */
  public void doBefore(JoinPoint jp) {
    strLog = "log Begining method: "
        + jp.getTarget().getClass().getName() + "."
        + jp.getSignature().getName();
    logger.warn(strLog);
  }
    /**
     * 环绕通知:包围一个连接点的通知,可以在方法的调用前后完成自定义的行为,也可以选择不执行
     * 类似Web中Servlet规范中的Filter的doFilter方法。
     * @param pjp 当前进程中的连接点
     * @return
     * @throws Throwable
     */
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long time = System.currentTimeMillis();
        Object retVal = pjp.proceed();
        time = System.currentTimeMillis() - time;
        System.out.println("process time: " + time + " ms");
        return retVal;
    }
    /**
     * 抛出异常后通知 : 在方法抛出异常退出时执行的通知。
     * @param jp 连接点:程序执行过程中的某一行为,例如,AServiceImpl.barA()的调用或者抛出的异常行为
     */
    public void doAfter(JoinPoint jp) {
    	strLog ="doAfter:log Ending method: "
    			+ jp.getTarget().getClass().getName() + "."
    			+ jp.getSignature().getName(); 
    	logger.warn(strLog);
    }
}

 

3、业务代码:

业务逻辑接口: 

package com.lzq.spring.service;

/**
 * 接口 AService
 */
public interface AService {
    public void cool(String _msg);
    public void cool();
}

 

业务接口的实现:

package com.lzq.spring.service;

/**
 * 接口的实现
 * @author lzq
 *
 */
public class AServiceImpl implements AService {
  @Override
  public void cool() {
    System.out.println("哇,楼主好帅!"); 
  }
  @Override
  public void cool(String name) {
    System.out.println("哇,楼主"+name+",你好帅啊!");
  }
}

 

4、测试AOPTest:

package com.lzq.spring.test;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathxmlapplicationContext;
import com.lzq.spring.service.AService;

public class AOPTest{
  public static void main(String[] args){
    BeanFactory factory = new ClassPathXmlApplicationContext("ApplicationContext.xml");
    AService aService = (AService)factory.getBean("aService");
    aService.cool();
    aService.cool("泉浴五江");
  }
}

 

5、Spring配置文件ApplicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd" 
      default-autowire="autodetect">
   <aop:config>  
        <aop:aspect id="aspect" ref="aspectBean">  
            <!--配置com.lzq.spring.service包下所有类或接口的所有方法-->  
            <aop:pointcut id="logService"  
                expression="execution(* com.lzq.spring.service.*.*(..))" />  
            <aop:before pointcut-ref="logService" method="doBefore"/>  
            <aop:after pointcut-ref="logService" method="doAfter"/>  
            <aop:around pointcut-ref="logService" method="doAround"/>  
        </aop:aspect>  
    </aop:config>  
    <bean id="aspectBean" class="com.lzq.spring.aop.Aspect" />  
    <bean id="aService" class="com.lzq.spring.service.AServiceImpl" />  
</beans>

 

6、log4j的properties文件主要配置:

### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=d:/test_log.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
log4j.rootLogger=warn, stdout,file
log4j.logger.org.hibernate.type=info
log4j.logger.org.hibernate.tool.hbm2ddl=debug
com.lzq.spring.service = debug

 

7、显示结果:

Console窗口

文件位置: 

日志文件内容: