2

我的控制器和服务注入有问题。在 Junit 测试中,所有数据都添加到数据库中,并且我的测试 junit 没有返回错误。但是当我在控制器中注入服务时,系统返回一个空对象而不是实例化:

我的服务:

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 没有注入,不明白为什么。你有什么主意吗 ?

非常感谢

4

2 回答 2

1

为了@Autowire工作,我们需要配置一些东西

  • <context:annotation-config />在 context.xml 中,你错过了这个。
  • xmlns:context="http://www.springframework.org/schema/context<beans ..标签中
  • Spring Sterio 类型注释等@Controller, @Component, @Service
于 2012-09-13T10:34:47.240 回答
0

那是因为在这一行:

final PlanningController avc = new PlanningController();    

您正在手动创建一个 bean 实例,而不是将其留给 spring,因此 spring 无法自动装配依赖项。

您应该将 bean 创建留给容器(在本例中为 spring)或自己设置 bean 属性。

在您的情况下,您可以使用访问 spring-managedPlanningController实例

applicationContext.getBean(PlanningController.class);
于 2012-09-13T10:28:45.903 回答