我已经在Spring配置中定义了一个数据源。
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
对于LOG4J2 JDBCAppender,我知道我们需要获取数据源:
<JDBC name="databaseAppender" tableName="error_log">
<ConnectionFactory class="net.example.db"
method="getDatabaseConnection" />
<Column name="EVENT_DATE" isEventTimestamp="true" />
<Column name="LEVEL" pattern="%level" />
<Column name="LOGGER" pattern="%logger" />
<Column name="MESSAGE" pattern="%message" />
<Column name="THROWABLE" pattern="%ex{full}" />
</JDBC>
我已将软件包添加到组件扫描中:
<context:component-scan base-package="com.test,net.example.db" />
在ConnectionFactory类中添加注释作为Component
import java.sql.Connection;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ConnectionFactory {
@Autowired
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public Connection getDatabaseConnection() throws Exception {
return dataSource.getConnection();
}
}
但是,当调用getDatabaseConnection()
时,我得到null2017-01-14 14:17:24,579 localhost-startStop-1 ERROR JdbcDatabaseManager jdbcManager{ description=databaseAppender, bufferSize=0, connectionSource=factory{ public static java.sql.Connection net.example.db.ConnectionFactory.getDatabaseConnection() }, tableName=error_log, columns=[ { name=EVENT_DATE, layout=null, literal=null, timestamp=true }, { name=LEVEL, layout=%level, literal=null, timestamp=false }, { name=LOGGER, layout=%logger, literal=null, timestamp=false }, { name=MESSAGE, layout=%message, literal=null, timestamp=false }, { name=THROWABLE, layout=%ex{full}, literal=null, timestamp=false } ] } Could not perform database startup operations: java.sql.SQLException: Failed to obtain connection from factory method. java.sql.SQLException: Failed to obtain connection from factory method.
at org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource$1.getConnection(FactoryMethodConnectionSource.java:107)
at org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource.getConnection(FactoryMethodConnectionSource.java:53)
at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.startupInternal(JdbcDatabaseManager.java:60)
at org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager.startup(AbstractDatabaseManager.java:65)
at org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.start(AbstractDatabaseAppender.java:89)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:255)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:530)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:258)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:239)
at org.apache.logging.log4j.core.config.Configurator.initialize(Configurator.java:158)
at org.apache.logging.log4j.web.Log4jWebInitializerImpl.initializeNonJndi(Log4jWebInitializerImpl.java:168)
at org.apache.logging.log4j.web.Log4jWebInitializerImpl.start(Log4jWebInitializerImpl.java:110)
at org.apache.logging.log4j.web.Log4jServletContainerInitializer.onStartup(Log4jServletContainerInitializer.java:57)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5604)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1571)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1561)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource$1.getConnection(FactoryMethodConnectionSource.java:105)
... 20 more
我怀疑当LOGJ2调用getDatabaseConnection()时是否还没有创建bean dataSource。请告诉我原因和解决方案。
答案 0 :(得分:3)
请完成本教程[Log4j2 JDBC](http://self-learning-java-tutorial.blogspot.in/2015/10/log4j2-jdbcappender-write-log-messages.html)
如上所述:请参阅此部分
以下是ConnectionFactory参数。
Class : Name of the class, that contains a static factory method for obtaining JDBC connections.
method : The name of a static factory method for obtaining JDBC connections. Method return type must be either java.sql.Connection or DataSource.
请注意,它需要静态工厂方法。这就是为什么反射调用失败。
答案 1 :(得分:2)
最后,我找到了一个解决方案。 LOG4J在Spring之前初始化,因此bean Datasource将返回null。
我按照以下网址的说明操作: How to use Spring BoneCPDataSource bean as data source for Log4j 2 JDBC appender?
现在一切都很好。