我可以在IDEA中很好地运行springboot项目,但是将其打包到jar中并使用java命令运行时,从spring上下文中获取bean时就得到了java.lang.NullPointerException。
第一次出现错误的课程:
@Service
public class MdspiImpl extends CThostFtdcMdSpi {
public MdspiImpl(CThostFtdcMdApi mdapi) {
m_mdapi = mdapi;
logger.info("MdspiImpl is creating...");
***mdr = SpringContextUtil.getBean("marketDataRobot");//this is the error code***
}
}
第二堂课
@Service
public class MarketDataRobot {
}
SpringContextUtil类:
@Component("SpringContextUtil")
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
}
gradle文件:
jar {
baseName = 'programmingTrading'
version = '0.1.0'
manifest {
attributes 'Main-Class': 'com.blackHole.programmingTrading'
}
}
正在运行的异常:
WARN main[AbstractApplicationContext.java:557 Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mdspiImpl' defined in URL [jar:file:/E:/workspace/simuPrd/programmingTrading-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/com/blackHole/programmingTrading/infrastructure/MdspiImpl.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.blackHole.programmingTrading.infrastructure.MdspiImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException]
[com.blackHole.programmingTrading.infrastructure.MdspiImpl]: Constructor threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:300)
... 27 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.blackHole.programmingTrading.SpringContextUtil.getBean(SpringContextUtil.java:35)
at com.blackHole.programmingTrading.infrastructure.MdspiImpl.<init>(MdspiImpl.java:46)
这也源于另一个问题:@Autowired注释不起作用... 像这样使用时:
@Component
public class Scu{
}
在另一堂课中:
@Autowired
private Scu scu;
logger.info(String.format("MdspiImpl is creating...[%s]", scu.toString()));
将获得java.lang.NullPointerException:空
spring-boot配置如下:
@SpringBootApplication
public class ProgrammingTrading {
public static void main(String[] args) {
SpringApplication.run(ProgrammingTrading.class, args);
}
}
这是使用SpringContextUtil获取Bean的部分原因... 非常感谢!
答案 0 :(得分:3)
SpringContextUtil
不应像您正在做的那样被静态访问...由于将其定义为@Component
,因此请执行以下操作;
@Service
public class MdspiImpl extends CThostFtdcMdSpi {
@Autowired
private SpringContextUtil springContextUtil;
public MdspiImpl(CThostFtdcMdApi mdapi) {
m_mdapi = mdapi;
logger.info("MdspiImpl is creating...");
***mdr = springContextUtil.getBean("marketDataRobot");
}
}
由于SpringContextUtil
不是通过Spring注入的,而是简单地静态访问的,它里面的applicationContext
被忽略,在您的情况下为空。
还删除static
修饰符;
@Component
public class SpringContextUtil implements ApplicationContextAware {
private ApplicationContext applicationContext;
// include getter/setter for applicationContext as well
public <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
}
修改
最新示例项目带来的麻烦;
@Service
public class ExampleService {
@Autowired
private Logger logger;
public ExampleService() {
this.logger=logger;
logger.info("Im working");
}
}
在触发Logger
构造函数时,ExampleService
将为null,因为在注入开始之前调用了该构造函数,但是如果通过所述构造函数合并注入,则可以合并此行为如下;
@Service
public class ExampleService {
private final Logger logger;
public ExampleService(Logger logger) {
this.logger = logger;
logger.info("Im working");
}
}
完美运行,没有任何麻烦...
答案 1 :(得分:2)
您永远不应该像使用此SpringContextUtil
那样以编程方式访问bean,只需将MarketDataRobot
注入MdspiImpl
的构造函数中,您就可以使用了(因为它带有{ {1}})。首选方法是使用构造函数注入而不是字段注入,这将使您更容易编写单元测试。如果只有一个构造函数,也可以摆脱@Service
。