2012-09-13 34 views
2

我有一個控制器和服務注入的問題。在Junit測試中,它正在將所有數據添加到數據庫中,並且我的測試團隊不會返回任何錯誤。但是,當我在控制器注入服務時,系統返回空對象,而不是實例:爲什麼Service沒有在Spring中注入Controller?

我的服務:

package mypackage.services 
public interface ExampleService { 
public abstract String helloWorld(); 
} 

package mypackage.services; 
import org.springframework.context.annotation.Scope; 
import org.springframework.stereotype.Service; 
@Service("exampleService") 
@Scope("singleton") 
public class ExampleServiceImpl implements ExampleService { 
@Override 
public String helloWorld(){ 
    return "Hello World !"; 
} 
} 

我的控制器:

package mypackage.controller; 

import javax.servlet.http.HttpServletRequest; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.context.ApplicationContext; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.servlet.ModelAndView; 

@Controller 
@RequestMapping("/planning") 
public class PlanningController { 

@Autowired 
public ExampleService exampleService; 

@RequestMapping(method = RequestMethod.GET) 
public final ModelAndView planning(final HttpServletRequest request) { 
    exampleService.helloWorld(); 
    final ModelAndView mav = new ModelAndView("planning", "tasks", "tasks"); 
    return mav; 
} 
} 

爲spring-servlet.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:p="http://www.springframework.org/schema/p" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" 
xmlns:jpa="http://www.springframework.org/schema/data/jpa" 
xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context.xsd 
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd 
    http://www.springframework.org/schema/jee 
    http://www.springframework.org/schema/jee/spring-jee-3.1.xsd 
    http://www.springframework.org/schema/data/jpa 
    http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> 


<!-- Use @Component annotations for bean definitions --> 
<context:component-scan base-package="mypackage.services" />           
<context:component-scan base-package="mypackage.controller" /> 

<!-- Use @Controller annotations for MVC controller definitions --> 
<mvc:annotation-driven /> 
<aop:aspectj-autoproxy proxy-target-class="true" /> 

<!-- View resolver --> 
<bean 
    class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix" value="/WEB-INF/" /> 
    <property name="suffix" value=".jsp" /> 
</bean> 
<bean 
    class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> 
    <property name="order" value="1" /> 
    <property name="mediaTypes"> 
     <map> 
      <entry key="json" value="application/json" /> 
     </map> 
    </property> 
    <property name="defaultViews"> 
     <list> 
      <!-- Renders JSON View --> 
      <bean 
       class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" /> 

     </list> 
    </property> 
</bean> 

<mvc:interceptors> 
    <!-- Resolve the device that originated the web request --> 
    <bean 
     class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" /> 
</mvc:interceptors> 

<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myDatasource" /> 
<tx:annotation-driven transaction-manager="transactionManager" /> 
<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="myPU" /> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="showSql" value="true" /> 
      <property name="database" value="ORACLE" /> 
     </bean> 
    </property> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.format_sql">true</prop> 
      <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> 
      <prop key="hibernate.hbm2ddl.auto">create</prop> 
      <prop key="hibernate.c3p0.maxSize">1</prop> 
      <prop key="hibernate.c3p0.minSize">1</prop> 
      <prop key="hibernate.c3p0.acquireIncrement">1</prop> 
      <prop key="hibernate.c3p0.idleTestPeriod">300</prop> 
      <prop key="hibernate.c3p0.maxStatements">0</prop> 
      <prop key="hibernate.c3p0.timeout">1800</prop> 
      <prop key="hibernate.c3p0.checkoutTimeout">0</prop> 
      <prop key="hibernate.c3p0.preferredTestQuery">SELECT * FROM dual</prop> 
     </props> 
    </property> 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

和我的web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

<display-name>Archetype Created Web Application</display-name> 

<servlet> 
    <servlet-name>spring</servlet-name> 
<servlet-class> 
    org.springframework.web.servlet.DispatcherServlet 
</servlet-class> 
<init-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>classpath:spring-servlet.xml</param-value> 
</init-param> 
<load-on-startup>1</load-on-startup>  
</servlet> 

<servlet-mapping> 
<servlet-name>spring</servlet-name> 
<url-pattern>*.html</url-pattern> 
<url-pattern>*.json</url-pattern> 
</servlet-mapping> 

<listener> 
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
    </listener> 
<context-param> 
<param-name>log4jConfigLocation</param-name> 
<param-value>classpath:log4j.xml</param-value> 
</context-param> 
<filter> 
    <filter-name>sitemesh</filter-name> 
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> 
    </filter> 

    <filter-mapping> 
<filter-name>sitemesh</filter-name> 
<url-pattern>/*</url-pattern> 
    </filter-mapping> 
    <resource-ref> 
<description>My DataSource Reference</description> 
<res-ref-name>jdbc/myDatasource</res-ref-name> 
<res-type>javax.sql.DataSource</res-type> 
<res-auth>Container</res-auth> 
    </resource-ref> 

    <session-config> 
    <session-timeout> 
    30 
    </session-timeout> 
    </session-config> 
    <welcome-file-list> 
    <welcome-file>index.jsp</welcome-file> 
    </welcome-file-list> 
    </web-app> 

我的測試:

... 
@Autowired 
private ApplicationContext applicationContext; 

@Test 
public void testPlanning() { 
    LOGGER.debug("Start testPlanning"); 

    boolean c = applicationContext.containsBean("exampleService"); 
    System.out.println(c); 

    final PlanningController avc = new PlanningController();   
    final Object mav = avc.planning(request); 
    Assert.assertEquals(200, response.getStatus()); 
    Assert.assertTrue(mav instanceof ModelAndView); 
    ModelAndViewAssert.assertViewName((ModelAndView) mav, "planning"); 
    final BindingResult result = mock(BindingResult.class); 
    when(result.hasErrors()).thenReturn(true); 
    LOGGER.debug("End testPlanning"); 
} 

我從我的測試類繼承:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:spring-servlet.xml"}) 
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, 
DirtiesContextTestExecutionListener.class, 
TransactionalTestExecutionListener.class, 
DbUnitTestExecutionListener.class}) 

public abstract class N2WIAppConfigTest { 

private static final Logger LOGGER = LoggerFactory 
     .getLogger(PlanningControllerTest.class); 

@BeforeClass 
public static void setUpClass() throws Exception { 
    // rcarver - setup the jndi context and the datasource 
    LOGGER.debug("CALL setUpClass"); 
    try { 
     // Create initial context 
     System.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
       "org.apache.naming.java.javaURLContextFactory"); 
     System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming"); 
     SimpleNamingContextBuilder builder = SimpleNamingContextBuilder 
       .emptyActivatedContextBuilder(); 
     // Construct DataSource 
     ComboPooledDataSource ds = new ComboPooledDataSource(); 
     ds.setDriverClass("oracle.jdbc.driver.OracleDriver"); 
     ds.setJdbcUrl("jdbc:oracle:thin:@localhost:1521:xe"); 
     ds.setUser("nemo2"); 
     ds.setPassword("nemo2"); 
     builder.bind("java:comp/env/jdbc/myDatasource", ds); 
     builder.activate(); 
    } catch (NamingException ex) { 
     System.out.println("###################################"); 
     ex.printStackTrace(); 

    } 

} 
} 

我在我的測試試圖加載的ApplicationContext,如果該服務被加載並且是這種情況。但是在PlanningController中,服務沒有被注入。

PlanningController中出現此問題。 ExampleService沒有注入,也不明白爲什麼。你有什麼主意嗎 ?

非常感謝

+0

這似乎對我好,你有'組件scan'和'斯特里奧類型annotations'配置正確,最後,你可以嘗試'@Autowired(required = true)',至少可以提供更多信息。 –

+0

我試過但沒有改變。我忘了:我在控制器的exampleService.heeloWorld()上收到一個NullPointerException異常。如果我在Autowired的測試中注入,那麼這個bean在控制器中不會被注入測試。我不明白 –

+0

@JonathanLebrun你有沒有任何理由爲什麼在spring-jpa中使用非版本化的xsd,在其他情況下使用spring-context和版本化的xsd? – soulcheck

回答

0

這是因爲在這一行:

final PlanningController avc = new PlanningController();  

您手動創建一個bean實例,而不是把它留給春天,所以春天有沒有辦法自動裝配依賴。

您應該將bean創建留給容器(在這種情況下爲spring)或者自己設置bean屬性。

在你的情況,你可以使用

applicationContext.getBean(PlanningController.class); 
+0

我試過了,問題再次出現。如果我在控制器exampleService.helloworld中刪除該行,則該行正在工作。 –

1

訪問春季管理PlanningController實例@Autowire在那裏工作設定的,我們需要配置

  • 在context.xml中<context:annotation-config />的事情, 你錯過了這個。
  • xmlns:context="http://www.springframework.org/schema/context<beans ..標籤
  • 春斯特里奧類型註釋像@Controller, @Component, @Service
+0

我加了它,問題再次出現。 –

相關問題