Spring Boot应用CommandLineRunner执行失败(空指针异常)求助
我正在开发一个Spring Boot应用,主类实现了CommandLineRunner接口,需要执行的代码放在重写的run()方法中。启动应用时遇到了NullPointerException,Stack Overflow上的现有解决方案没能解决我的问题,请求帮助排查并解决。
代码片段
应用主类代码
package com.First_Spring.Database_My_Spring; import com.First_Spring.Database_My_Spring.Entities.Person; import com.First_Spring.Database_My_Spring.JDBC.Person_JDBC_DAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DatabaseMySpringApplication implements CommandLineRunner{ @Autowired Person_JDBC_DAO person_jdbc_dao; public static void main(String[] args) { SpringApplication.run(DatabaseMySpringApplication.class, args); } @Override public void run(String... args) throws Exception { System.out.println( person_jdbc_dao.find_All() ); } }
application.properties配置
spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=create spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.First_Spring</groupId> <artifactId>Database_My_Spring</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Database_My_Spring</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
启动错误日志
2020-06-19 19:54:40.072 INFO 22134 --- [ main] ConditionEvaluationReportLoggingListener : Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2020-06-19 19:54:40.081 ERROR 22134 --- [ main] o.s.boot.SpringApplication : Application run failed java.lang.IllegalStateException: Failed to execute CommandLineRunner at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:779) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:322) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] at com.First_Spring.Database_My_Spring.DatabaseMySpringApplication.main(DatabaseMySpringApplication.java:18) ~[classes/:na] Caused by: java.lang.NullPointerException: null at com.First_Spring.Database_My_Spring.JDBC.Person_JDBC_DAO.find_All(Person_JDBC_DAO.java:18) ~[classes/:na] at com.First_Spring.Database_My_Spring.JDBC.Person_JDBC_DAO$$FastClassBySpringCGLIB$$f0cd1232.invoke(<generated>) ~[classes/:na] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.7.RELEASE.jar:5.2.7.RELEASE] at com.First_Spring.Database_My_Spring.JDBC.Person_JDBC_DAO$$EnhancerBySpringCGLIB$$e3e35047.find_All(<generated>) ~[classes/:na] at com.First_Spring.Database_My_Spring.DatabaseMySpringApplication.run(DatabaseMySpringApplication.java:25) ~[classes/:na] at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE] ... 5 common frames omitted
问题分析与解决方案
从错误栈可以看出,NullPointerException发生在Person_JDBC_DAO的find_All()方法第18行,而且Spring已经通过CGLIB生成了DAO的代理类,说明person_jdbc_dao本身已经被Spring正确注入,问题出在DAO内部的某个依赖对象为null,最常见的情况是**JdbcTemplate未被正确注入**。
步骤1:确保Person_JDBC_DAO被Spring容器管理
在Person_JDBC_DAO类上添加@Repository注解,让Spring自动扫描并将该类注册为容器中的Bean:
package com.First_Spring.Database_My_Spring.JDBC; import com.First_Spring.Database_My_Spring.Entities.Person; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import java.util.List; @Repository public class Person_JDBC_DAO { // 推荐使用构造函数注入(Spring 4.3+无需额外添加@Autowired) private final JdbcTemplate jdbcTemplate; public Person_JDBC_DAO(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<Person> find_All() { String sql = "SELECT * FROM person"; // 使用注入的jdbcTemplate执行查询,避免空指针 return jdbcTemplate.query(sql, (rs, rowNum) -> { Person person = new Person(); person.setId(rs.getInt("id")); person.setName(rs.getString("name")); // 补充其他属性的映射逻辑 return person; }); } }
步骤2:检查find_All()方法的实现
确保方法中没有使用未初始化的对象,比如不要手动实例化JdbcTemplate,一定要通过Spring依赖注入获取实例。
步骤3:优化依赖配置
你的pom.xml同时引入了spring-boot-starter-data-jdbc和spring-boot-starter-data-jpa,如果仅使用JDBC操作数据库,可以移除spring-boot-starter-data-jpa依赖,避免潜在的配置冲突。
步骤4:验证包扫描范围
@SpringBootApplication默认扫描主类所在包及其子包,你的Person_JDBC_DAO在com.First_Spring.Database_My_Spring.JDBC包下,属于主类包的子包,扫描范围是正常的。如果DAO在其他包,需要添加@ComponentScan指定额外的扫描路径。
按照以上步骤调整后,重新启动应用即可解决空指针问题。
内容的提问来源于stack exchange,提问作者Sunny Khandare

