Spring中new出一个对象导致的空指针异常
报错概述
背景
单体项目升级微服务时,在BeforeSave_2250042
中调用了一个公共模块CommonVerifyHandler
的verifySeal()
方法,但是运行时显示空指针异常
代码
根据断点和报错信息可以看到是这里出错
大致报错内容
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2715c179] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@bd1cd86] will not be managed by Spring
==> Preparing: select count(1) from 签约主体映射组织视图 where 签约主体编号=? and 组织编号 = ?
==> Parameters: QYZT-0001(String), ORG100000(String)
<== Columns: COUNT(1)
<== Row: 1
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2715c179]
[http-nio-8075-exec-1] 01/26 21:51:18.703 ERROR [c.d.s.beforesave.BeforeSave_2250042] - 不涉及金额合同 保存前事件处理异常,功能编号:2250042,单据ID:624060420265480192,错误信息:{}
java.lang.NullPointerException: null
at com.dhcc.sdg.beforeinsert.CommonVerifyHandler.verifySeal(CommonVerifyHandler.java:41)
at com.dhcc.sdg.beforesave.BeforeSave_2250042.doBefore(BeforeSave_2250042.java:46)
at
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79a446c1] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@bd1cd86] will not be managed by Spring
==> Preparing: SELECT 集团内外 FROM 签约方信息视图 WHERE 签约方编号= ? AND DELETED_MARK =0
==> Parameters: GYS-2022-013436(String)
<== Columns: 集团内外
<== Row: 0
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79a446c1]
CommonVerifyHandler
@Component
public class CommonVerifyHandler {
@Autowired
public CommonVerifyHandlerMapper commonVerifyHandlerMapper;
/**
* 验证印章 xlm
*/
public boolean verifySeal(BillData billData){
boolean result = true;
String PHY_ID = billData.getMasterData().get("PHY_SEAL_ID").toString().trim();
String PHY_PARTY_ID = getSignPhyId( billData);
System.out.println("PHY_ID:"+PHY_ID+",PHY_PARTY_ID:"+PHY_PARTY_ID);
System.out.println("开始执行commonVerifyHandlerMapper.sealInfo");
List<String> maps = commonVerifyHandlerMapper.sealInfo(PHY_ID, PHY_PARTY_ID);
System.out.println("map:"+maps);
if (maps == null || maps.isEmpty()) {
result = false;
}
return result;
}
}
错误一:
commonVerifyHandler
没有加入@Component
注解被Spring管理
错误二:
在BeforeSave_2250042
中commonVerifyHandler
没有被注入,相当于于commonVerifyHandler
是new出来的
在Spring管理的类中直接通过new
关键字来创建一个对象(模块)时,Spring容器本身是不会自动识别和管理这个新创建的对象的。Spring容器负责管理和装配的是那些被它自己创建和初始化的bean。
使用new
来创建一个对象时,这个对象是在Spring容器的控制之外的,也就是说,它不会享受到Spring容器的任何服务,比如依赖注入、事务管理、AOP等。
如果想要Spring容器能够识别并管理一个对象,需要将这个对象声明为一个Spring bean。这可以通过在类上添加@Component
、@Service
、@Repository
或@Controller
等注解来实现,或者在Spring的配置文件中显式地声明这个bean。
如果确实需要在Spring管理的类中创建一个新的对象,并且希望这个对象能够享受到Spring容器的某些服务,你可以考虑使用ApplicationContext.getBean()
方法来从Spring容器中获取这个对象,而不是直接使用new
来创建它。但是,这要求这个对象必须已经被声明为一个Spring bean,并且已经被Spring容器初始化和管理。
另外,如果想要Spring容器能够管理通过new
关键字创建的对象的某些方面,可以考虑使用AspectJ等AOP框架来在运行时动态地为这些对象添加额外的行为。但是,这通常会增加系统的复杂性和维护成本,因此应该谨慎使用。
总之,直接在Spring管理的类中通过new
来创建一个对象通常不是一个好的做法,除非有特殊的理由需要这样做,并且了解这样做可能带来的后果。更好的做法是让Spring容器来负责对象的创建和管理,这样可以确保对象能够享受到Spring容器提供的所有服务,并且更容易地进行单元测试和集成测试。