java - 还有一个 ApplicationContext 为 Null

标签 java spring inversion-of-control applicationcontext

我在应用程序中 Autowiring Spring bean 时遇到问题。这是我之前在其他应用程序中成功完成的事情,但由于某种原因我被难住了。我用谷歌搜索了一下,发现很多人都有同样的麻烦,并且使用 getApplicationContext() 方法时出现警告,但没有任何答案对我有帮助。我理解这些警告,并且仍然有一种情况我想这样做,那么也许我会使用 AspectJ 和编译时编织让它工作。

这是我的设置:

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:oxm="http://www.springframework.org/schema/oxm"
        xmlns:util="http://www.springframework.org/schema/util"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/oxm
        http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.0.xsd">

        <context:property-placeholder location="classpath:widgetClient.properties"/>
        <context:component-scan base-package="com.myCompany.widget.domain" />
        <context:component-scan base-package="com.myCompany.widget.services" />
        <context:annotation-config />


        <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
            <property name="basename" value="messages" />
        </bean>

        <bean id="heartbeat" class="com.company.widget.domain.CheckWidgetServerHeartbeat" destroy-method="destroy">
            <constructor-arg type="java.lang.Integer" name="interval" value="${heartbeat.interval}"/>
            <constructor-arg type="java.lang.Integer" name="timeout" value="${heartbeat.timeout}"/>
            <constructor-arg type="java.lang.Integer" name="unhealthyThreshold" value="${unhealthy.threshold}"/>
            <constructor-arg type="java.lang.Integer" name="healthyThreshold" value="${healthy.threshold}"/>
            <constructor-arg type="java.lang.Integer" name="backupVerifyTime" value="${backup.verify.time}"/>
            <constructor-arg type="java.lang.String"  name="apiServerUrl" value="${api.server.url}" />
        </bean>
    </beans>

BaseService.java

package com.company.widget.services;

import com.company.widget.domain.CheckWidgetServerHeartbeat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class BaseService{

    @Autowired
    private ApplicationContext appContext;

    public BaseService(){}

    public CheckWidgetServerHeartbeat getHeartbeat(){
        return (CheckWidgetServerHeartbeat) appContext.getBean("heartbeat");
    }
}

Heartbeatservice.java

package com.company.widget.services;

import org.springframework.stereotype.Service;

import org.apache.log4j.Logger;

@Service
public class HeartbeatService extends BaseService{

    private static final Logger logger = Logger.getLogger(HeartbeatService.class);

    public HeartbeatService(){}

    public Boolean isHealthy(){
        return getHeartbeat().check();
    }
}

CompanyWidgetClient.java

package com.company.widget.domain;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Locale;
import java.util.ResourceBundle;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.*;

import com.company.widget.services.HeartbeatService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class CompanyWidgetClient{



@Autowired
private HeartbeatService heartbeatService;

public CompanyWidgetClient(String settingsXmlFilePath, HttpServletRequest request){
    if(settingsXmlFilePath != null){            
        configuration = new CompanyWidgetConfiguration(settingsXmlFilePath, request);
    }
    if(request != null){
        this.request = request;
    }

    //Use API server URL from settings file if it is present
    if (configuration.getProperty("api_server_url") != null) {
        this.apiServerUrl = configuration.getProperty("api_server_url");
        log.debug("Set api_server_url to " + this.apiServerUrl + " which was found in settings.xml");
    }
} 

public CompanyWidgetClient(CompanyWidgetConfiguration configuration, HttpServletRequest request){
    if(configuration != null){
        this.configuration=configuration;
    }
    if(request != null){
       this.request = request;
    }
    //Use API server URL from settings file if it is present
    if (configuration.getProperty("api_server_url") != null) {
       this.apiServerUrl = configuration.getProperty("api_server_url");
       log.debug("Set api_server_url to " + this.apiServerUrl + " which was found in settings.xml");
    }
}

public CompanyWidgetClient(){}

    private CompanyWidgetResponse requestWidget(){
        if(heartbeatService.isHealthy()){
            do stuff...
        }

index.jsp

<%@ page import="com.company.widget.domain.*" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    CompanyWidgetClient widgetClient = new CompanyWidgetClient("/WEB-INF/settings.xml", request);
    String companyWidgetComponent = widgetClient.createWidget();
%>
...
HTML stuff

...

<div id="widget">
    <%=companyWidgetComponent%>
</div>

...

错误:

500

org.apache.jasper.JasperException: An exception occurred processing JSP page /index.jsp at line 5

2: <%@ page contentType="text/html;charset=UTF-8" language="java" %> 3: <% 4:     CompanyWidgetClient widgetClient = new CompanyWidgetClient("/WEB-INF/settings.xml", request); 5:     String companyWidgetComponent = widgetClient.createWidget(); 6: %> 7: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 8: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause

java.lang.NullPointerException
    com.company.widget.domain.CompanyWidgetClient.requestWidget(CompanyWidgetClient.java:553)
    com.company.widget.domain.CompanyWidgetClient.createWidget(CompanyWidgetClient.java:603)
    org.apache.jsp.index_jsp._jspService(index_jsp.java:67)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

观察结果:

我知道我遗漏了一些东西,因为它需要 CompanyClient 对象上存在默认构造函数,并且它记录它在部署时构建 CompanyClient 对象。我想我对 Spring 应用程序上下文的范围不是很清楚。我的理解是,无论调用 bean 的范围如何,都应该使用应用程序上下文来使用单例 bean。非常感谢任何和所有的帮助!

最佳答案

当您直接实例化 CompanyWidgetClient 时:

new CompanyWidgetClient(...)

您没有给 spring DI 容器注入(inject) HeartbeatService 实例的机会 - 所以它为 null。

当获取 CompanyWidgetClient 的实例时 - 从 Spring Applicaiton Context 检索实例(通过 getBean() 或类似方法) - 这样 HeartbeatService 将被 Autowiring 。

关于java - 还有一个 ApplicationContext 为 Null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22901043/

相关文章:

c# - 如何在 C# .NET 中像 Java 代码一样加密

java - JFreeChart PolarPlot : mathematical orientation

java - 如何将 JDK6 ToolProvider 和 JavaCompiler 与上下文类加载器一起使用?

spring - Spring Boot 和 RestAssured 中的模拟 session

java - Spring批量并行处理

dependency-injection - 如何使用 Ninject 在子类中创建实例?

java - DES-加密字节数组,java

spring - 当多个配置文件不活动时如何有条件地声明 Bean?

c# - 如何在 CaSTLe.Windsor 中配置提供多个服务的单个组件实例?

inversion-of-control - 哪些 IOC 容器可与 Windows Azure 配合使用