通过@Autowired访问时的NPE
NPE while accessing through @Autowired
我的 SpringBoot 项目中有以下代码,它在提到的特定行中抛出 NPE。
Exception in thread "main" java.lang.NullPointerException
at com.temp.controller.Controller.triggerJob(Controller.java:15)
at com.temp.Application.main(Application.java:19)
Application.java
@Configuration
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller();
controller.triggerJob();
}
}
Controller.java
@Controller
public class Controller {
@Autowired
private Service Service;
public void triggerJob() {
Service.selectRecords();
}
}
Service.selectRecords(); is where the NPE is being thrown
Service.java
public interface Service {
List<VO> selectRecords();
}
ServiceImpl.java
@Service
public class ServiceImpl implements Service {
@Autowired
private Dao dao;
@Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<util:properties id="configProperties"
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<context:property-placeholder
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<bean id="crypt" class="com.temp.util.MyUtil">
<property name="userId" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="key" value="123456789012345678901234"></property>
</bean>
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${connection}" />
<property name="username" value="#{crypt.userId}" />
<property name="password" value="#{crypt.password}" />
</bean>
<bean id="namedJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="datasource" />
</bean>
</beans>
我有一个类似的项目,比较了两者的配置,除了两点外它们是相同的。
- 本项目的 spring 启动版本是 2.4.2,另一个项目是 1.5.3。
- Java 这个项目的版本是 11,另一个项目的版本是 1.8。
不确定我哪里出错了。
我错过了什么吗?请帮忙。
您正在创建新实例
Controller controller = new Controller();
手动并且此实例不在 Spring 上下文中。因此,服务的注入(自动装配)实例为空。 @Autowired
仅当实例存在于 Spring 上下文中时才有效。
保持 Controller 可测试的最佳方法是通过构造函数注入:
@Configuration
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller(new ServiceImpl(new DaoImpl()));
controller.triggerJob();
}
}
通过构造函数注入实例:
@Controller
public class Controller {
private final Service Service;
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}
并通过构造函数注入 Dao 依赖:
@Service
public class ServiceImpl implements Service {
private final Dao dao;
public ServiceImpl(final Dao dao) {
this.dao = dao;
}
@Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
对于Spring 4.3 以上的版本,@Autowired
可以从构造函数的顶部省略,Spring 会自动扫描注入并通过构造函数注入依赖项。
对于 4.3 以下的 Spring 版本,在构造函数之上添加 @Autowired
即:
@Controller
public class Controller {
private final Service Service;
@Autowired
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}
我的 SpringBoot 项目中有以下代码,它在提到的特定行中抛出 NPE。
Exception in thread "main" java.lang.NullPointerException at com.temp.controller.Controller.triggerJob(Controller.java:15) at com.temp.Application.main(Application.java:19)
Application.java
@Configuration
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller();
controller.triggerJob();
}
}
Controller.java
@Controller
public class Controller {
@Autowired
private Service Service;
public void triggerJob() {
Service.selectRecords();
}
}
Service.selectRecords(); is where the NPE is being thrown
Service.java
public interface Service {
List<VO> selectRecords();
}
ServiceImpl.java
@Service
public class ServiceImpl implements Service {
@Autowired
private Dao dao;
@Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<util:properties id="configProperties"
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<context:property-placeholder
location="file:${app.config.home}/config/config-${spring.profiles.active}.properties" />
<bean id="crypt" class="com.temp.util.MyUtil">
<property name="userId" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="key" value="123456789012345678901234"></property>
</bean>
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${connection}" />
<property name="username" value="#{crypt.userId}" />
<property name="password" value="#{crypt.password}" />
</bean>
<bean id="namedJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="datasource" />
</bean>
</beans>
我有一个类似的项目,比较了两者的配置,除了两点外它们是相同的。
- 本项目的 spring 启动版本是 2.4.2,另一个项目是 1.5.3。
- Java 这个项目的版本是 11,另一个项目的版本是 1.8。
不确定我哪里出错了。
我错过了什么吗?请帮忙。
您正在创建新实例
Controller controller = new Controller();
手动并且此实例不在 Spring 上下文中。因此,服务的注入(自动装配)实例为空。 @Autowired
仅当实例存在于 Spring 上下文中时才有效。
保持 Controller 可测试的最佳方法是通过构造函数注入:
@Configuration
@SpringBootApplication
@ImportResource({"classpath:applicationContext.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Controller controller = new Controller(new ServiceImpl(new DaoImpl()));
controller.triggerJob();
}
}
通过构造函数注入实例:
@Controller
public class Controller {
private final Service Service;
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}
并通过构造函数注入 Dao 依赖:
@Service
public class ServiceImpl implements Service {
private final Dao dao;
public ServiceImpl(final Dao dao) {
this.dao = dao;
}
@Override
public List<VO> selectRecords() {
return dao.selectRecords();
}
}
对于Spring 4.3 以上的版本,@Autowired
可以从构造函数的顶部省略,Spring 会自动扫描注入并通过构造函数注入依赖项。
对于 4.3 以下的 Spring 版本,在构造函数之上添加 @Autowired
即:
@Controller
public class Controller {
private final Service Service;
@Autowired
public Controller(final Service Service) {
this.service = service;
}
public void triggerJob() {
Service.selectRecords();
}
}