Java EE中@Inject注入对象为空指针异常排查求助
解决Hibernate WebService中依赖注入为空的问题
你遇到的核心问题是依赖注入(DI)未生效,导致db变量始终为null,IDE的“Class not loaded”提示也和这个根源相关——因为容器没托管这些类,调试时类加载器无法正确识别它们。下面一步步帮你排查解决:
1. 确保依赖注入容器正常工作
JAX-RS本身不自带DI容器,通常我们用CDI(Contexts and Dependency Injection)实现@Inject功能。先做这两步:
- 确认项目引入了CDI相关依赖(如果用Java EE容器如WildFly、GlassFish,它们自带CDI;如果是Tomcat这类轻量容器,需要手动引入Weld或OpenWebBeans)
- 在
src/main/resources/META-INF目录下创建beans.xml文件(空文件也可以,CDI需要它开启类扫描):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" version="2.0" bean-discovery-mode="all"> </beans>
bean-discovery-mode="all"会让CDI扫描所有类,识别需要托管的Bean。
2. 让需要注入的类成为CDI托管Bean
你的dbController和HibernateUtil目前是普通Java类,CDI不知道要为它们创建实例并管理依赖,所以@Inject不会生效。给这些类加上CDI作用域注解:
修改dbController:
import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; @ApplicationScoped // 标注为应用级单例Bean,全局共享实例 public class dbController { @Inject private HibernateUtil util; public List<UserEntity> getUsers(){ List<UserEntity> result = null; try{ result = (List<UserEntity>) this.util.createQuery("select e from UserEntity e"); }catch (Exception e){ System.out.println(e.getMessage()); } return result; } }
修改HibernateUtil:
import javax.enterprise.context.Singleton; @Singleton // 单例注解,确保EntityManagerFactory只初始化一次(重量级资源) public class HibernateUtil { private static final EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit"); private EntityManager entityManager = null; private void createEntityManager(){ if (this.entityManager==null){ this.entityManager = entityManagerFactory.createEntityManager(); } } private void closeConnection(){ if (this.entityManager != null && this.entityManager.isOpen()) { this.entityManager.close(); this.entityManager = null; } } public List createQuery(String query) throws Exception{ this.createEntityManager(); List result; try{ result = this.entityManager.createQuery(query).getResultList(); }catch (Exception e){ throw new Exception(e.getMessage()); } finally { this.closeConnection(); // 方法结束后关闭连接,避免泄漏 } return result; } }
这里给HibernateUtil加@Singleton是因为EntityManagerFactory是重量级资源,全局只初始化一次更合理,同时补充了finally块关闭连接,避免数据库连接泄漏。
3. 确保JAX-RS服务类被容器托管
你的BookService是JAX-RS资源类,需要让它被CDI或JAX-RS容器管理。可以给它加上请求作用域注解:
import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.enterprise.context.RequestScoped; @Path("/book") @RequestScoped // 标注为请求作用域Bean,每个请求创建一个实例 public class BookService { @Inject private dbController db; @GET @Produces(MediaType.TEXT_PLAIN) public String getBookTitle() { return "H2G2"; } @GET @Path("/users") @Produces(MediaType.APPLICATION_JSON) public Response getUsers(){ List<UserEntity> users = db.getUsers(); return Response.ok(users,MediaType.APPLICATION_JSON).build(); } }
或者通过JAX-RS的Application子类注册这个服务:
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashSet; import java.util.Set; @ApplicationPath("/") // 对应你的请求根路径http://localhost/book/users public class MyApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); classes.add(BookService.class); return classes; } }
4. 解决IDE的“Class not loaded”提示
这个问题通常是调试时类还没被应用服务器的类加载器加载。先解决上面的DI问题,重新部署项目后,当请求触发getUsers()方法时,容器会自动加载dbController类,此时调试断点就能正常识别了。如果还是有问题,可以检查:
- 项目部署配置,确保所有类都被打包到war文件中
- IntelliJ的调试配置,选择正确的应用服务器实例
额外注意点
- 确认
UserEntity是正确的JPA实体类,带有@Entity注解,并且在persistence.xml中注册 - 检查
persistence.xml里的NewPersistenceUnit配置是否正确,确保能连接到数据库
内容的提问来源于stack exchange,提问作者SMt
相关产品推荐
相关产品推荐

