2014-09-04 177 views
0

要在我的log4j appender中使用数据源,我写了一个自定义appender。 appender试图将数据源作为spring bean获取。但是,appender无法获取该bean。我使用的技术堆栈是:mybatis,tomcat和spring。log4j自定义jdbc appender,数据源

我log4j的文件看起来像这样:

#configuring the requestinterceptor 
log4j.category.com.db.wscis.core.web.interceptor=INFO, sql 
log4j.appender.sql=com.db.wscis.core.util.appender.CustomJDBCAppender 
log4j.appender.sql.sql=INSERT INTO LOGS VALUES ('%x', current_timestamp ,'%C','%p','%m') 
log4j.appender.sql.layout=org.apache.log4j.PatternLayout 

自定义附加器的代码如下:

public class CustomJDBCAppender extends org.apache.log4j.jdbc.JDBCAppender { 

protected java.sql.Connection getConnection() throws java.sql.SQLException { 

     if(connection == null) { 
      org.springframework.jdbc.datasource.DataSourceTransactionManager dstm = (org.springframework.jdbc.datasource.DataSourceTransactionManager) ExternalBeanFactory.getBean("txManager"); 
      if(dstm==null) throw new java.sql.SQLException("dstm is null"); 
      System.out.println("here"); 
      connection = DataSourceUtils.getConnection(dstm.getDataSource()); 
      return connection; 
     } else{ 
      return connection; 
     } 
    } 

    /* protected void execute(String sql) throws java.sql.SQLException { 

     Connection con = null; 
     Statement stmt = null; 

     try { 
      con = getConnection(); 
      stmt = con.createStatement(); 
      stmt.executeUpdate(sql); 
      con.commit(); 
     } catch (SQLException e) { 
      if (stmt != null) 
       stmt.close(); 
      closeConnection(con); 
      throw e; 
     } 
     } 
    */ 
    protected void closeConnection() throws java.sql.SQLException { 
      if (connection != null && !connection.isClosed()) 
        connection.close(); 
    } 
} 

外部bean工厂类看起来像这样:

/* 
*/  
package com.db.wscis.core.util; 

import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.BeanFactory; 
import org.springframework.beans.factory.BeanFactoryAware; 

public class ExternalBeanFactory implements BeanFactoryAware { 

    /** 
    * Bean factory instance. 
    */ 
    private static BeanFactory beanFactory; 

    /** 
    * Sets beanfactory. 
    * 
    * @param beanFactory 
    *   BeanFactory object 
    * 
    * @see org.springframework.beans.factory.BeanFactoryAware# 
    *  setBeanFactory(org.springframework.beans.factory.BeanFactory) 
    * @exception BeansException 
    *    if failed to set factory 
    */ 
    public final void setBeanFactory(final BeanFactory beanFactory) throws BeansException { 
     this.beanFactory = beanFactory; 
    } 

    /** 
    * DO NOT use this method in the application classes. This is meant to be 
    * used by the framework level classes ONLY!!!! 
    * 
    * Finds from bean from the factory. 
    * 
    * @param beanName 
    *   Name of the bean 
    * @return bean object 
    */ 
    @Deprecated 
    public static final Object getBean(final String beanName) { 
    // if(beanFactory==null) System.out.println("Bean factory is null"); 
     return beanFactory.getBean(beanName); 
    } 

    public final Object getBeanInstance(final String beanName) { 
     return beanFactory.getBean(beanName); 
    } 
} 

现在,当tomcat服务器启动时,我的猜测是它试图初始化log4j。因此,它调用了自定义appender中的getConnection方法。这个inturn调用ExernalFactory.getBean(),但是,External BeanFactory中的beanfactory属性尚未初始化。
错误堆栈跟踪如下:

SEVERE: Error configuring application listener of class com.db.wscis.core.web.context.FWContextLoaderLis 
java.lang.NullPointerException 
     at com.db.wscis.core.util.ExternalBeanFactory.getBean(ExternalBeanFactory.java:64) 
     at com.db.wscis.core.util.appender.CustomJDBCAppender.getConnection(CustomJDBCAppender.java:27) 
     at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:215) 
     at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:289) 
     at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:186) 
     at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251) 
     at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl. 
     at org.apache.log4j.Category.callAppenders(Category.java:206) 
     at org.apache.log4j.Category.forcedLog(Category.java:391) 
     at org.apache.log4j.Category.log(Category.java:856) 
     at org.apache.commons.logging.impl.Log4JLogger.info(Log4JLogger.java:176) 
     at com.db.wscis.core.web.context.FWContextLoaderListener.<init>(FWContextLoaderListener.java:34) 
     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) 
     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.j 
     at java.lang.reflect.Constructor.newInstance(Constructor.java:526) 
     at java.lang.Class.newInstance(Class.java:374) 
     at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:140) 
     at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4888) 
     at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467) 
     at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 
     at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) 
     at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) 
     at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632) 
     at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1073) 
     at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857) 
     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 
     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
     at java.lang.Thread.run(Thread.java:724) 

请告诉我什么,我做错了,我怎么能得到的数据源bean实例在我的appender类。

+1

你可以修复格式吗?谢谢! – admdrew 2014-09-04 16:23:12

+0

@anmdrew:你能帮助解决这个问题吗? – TimeToCodeTheRoad 2014-09-05 02:19:55

+1

@TimeToCodeTheRoad Spring的哪个版本?你在你的web.xml中使用它的servlet或它的liste? – 2014-09-05 23:37:15

回答

0

我设法解决这个问题:

因此,我的数据源bean是在应用程序上下文中声明的。另一方面,我的外部bean工厂在根上下文中声明。现在,根上下文中的bean不能在应用程序上下文中看到bean。所以,我的External Bean Factory中的beanfactory属性从未被初始化。我花了一些时间才弄明白,但谢天谢地,它奏效了!