не может получить бин при запуске фляги, упакованной из проекта весенней загрузки - PullRequest
3 голосов
/ 11 июля 2019

Я могу хорошо запустить свой проект springboot в IDEA, но когда упаковал его в jar и запустил с помощью команды java, я получил только исключение java.lang.NullPointerException при получении компонента из контекста Spring.

первыйкласс, который только что получил ошибки:

@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: null

конфигурацию с пружинной загрузкой, подобную этой:

@SpringBootApplication
public class ProgrammingTrading {
    public static void main(String[] args) {
        SpringApplication.run(ProgrammingTrading.class, args);
    }
}

, что является частью причин использованияSpringContextUtil, чтобы получить бин ... большое спасибо!

Ответы [ 2 ]

3 голосов
/ 11 июля 2019

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, так как конструктор вызывается до начала внедрения, но вы можете объединить это поведение, если внедрите инъекцию через указанный конструктор следующим образом;

@Service
public class ExampleService {

    private final Logger logger;

    public ExampleService(Logger logger) {
        this.logger = logger;
        logger.info("Im working");
    }
}

Работает отлично, без проблем ...

2 голосов
/ 11 июля 2019

Вы никогда не должны обращаться к bean-компонентам программно, как вы это сделали с этим SpringContextUtil, просто введите MarketDataRobot в конструктор MdspiImpl, и все готово (так как оно аннотировано @Service). Предпочтительным способом является использование инжектора конструктора вместо полевого, что облегчит вам написание модульных тестов. Вы также можете избавиться от @Autowired, если у вас есть только один конструктор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...