简体   繁体   中英

Spring @Autowired instance is null

I'm currently trying to setup a REST Service Spring application and have implemented a model and its controller + the dao and service to talk to a MySQL database.

在此处输入图片说明

Now my AccountController is a bean with annotated @RestController, while AccountService is a @Component bean. The AccountService holds an @Autowire'd AccountDao member and AccountController holds an @Autowire'd AccountService member.

The dataAccess.xml is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/fashion" />
        <property name="username" value="root" />
        <property name="password" value="fashion" />
    </bean>

    <bean id="sessionFactory"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mappingResources">
            <list>
                <value>de/appsiting/fashion/model/Account.hbm.xml</value>
           </list>
        </property>
        <property name="hibernateProperties">
           <props>
                <prop key="hibernate.dialect">
                org.hibernate.dialect.MySQL5Dialect
                </prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
           </props>
        </property>
    </bean>

    <bean id="jdbcExceptionTranslator" class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator">
       <property name="dataSource">
            <ref bean="dataSource" />
       </property>
    </bean>

    <bean id="accountDao" class="de.appsiting.fashion.persistence.AccountDao" />
</beans>

However the Account.hbm.xml is colored in red indicating it isn't found by the application. Thus my first question, why doesn't it root from resources folder to find the .hbm.xml

The serviceBeans.xml is filled as follows:

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <task:annotation-driven/>

    <bean id="hibernateStringEncryptor" class="org.jasypt.hibernate4.encryptor.HibernatePBEStringEncryptor">
        <property name="registeredName">
            <value>strongHibernateStringEncryptor</value>
        </property>
        <property name="algorithm">
            <value>PBEWithMD5AndTripleDES</value>
        </property>
        <property name="password">
            <value>jasypt</value>
        </property>
    </bean>

    <bean id="accountService" class="de.appsiting.fashion.service.AccountService">
        <property name="accountDao" ref="accountDao" />
    </bean>

    <!-- *** TX LAYER -->
    <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <tx:advice id="tx.advice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false" />
            <tx:method name="get*" propagation="REQUIRED" read-only="false" />
        </tx:attributes>
    </tx:advice>

    <!-- *** AOP -->
    <aop:config>
        <aop:pointcut id="accountServiceMethods" expression="execution(* de.appsiting.fashion.service.AccountService.*(..))" />

        <aop:advisor advice-ref="tx.advice" pointcut-ref="accountServiceMethods" />
    </aop:config>
</beans>

Now when running my AccountTest the accountService is null and thus the Test fails:

import de.appsiting.fashion.service.AccountService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.Test;


/**
 * Created by mak on 4/22/16.
 */
public class AccountTest {
    private static Logger log = Logger.getLogger(AccountTest.class);

    @Autowired
    private AccountService accountService;

    @Test
    public void testCreateAccount() throws Exception {
        Account account = new Account();
        account.setUsername("testfashion");
        account.setPassword("testfashion");
        account.setEmail("test@appsiting");

        accountService.addAccount(account);
    }
}

Why does this happen?

You should use SpringJUnit4ClassRunner in order to initialize the application context, so the dependency injection is able to run.

Another option is to use Mockito , which in IMHO avoids lots of troubles and you get the benefits of using mocks.

You are missing two configurations on your tests.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"Location of xml files that you need to load for tests to run"})
public class AccountTest {

}

Above configuration will load the context for your tests. Or you can load the application context for your tests in the setup method and then use that context you get your account service.

I think you should add the following in your serviceBeans.xml,

<bean id="accountDao" class="de.appsiting.fashion.persistence.AccountDao" />

and delete the @Autowired AccountDao annotation in the AccountService class and add a setter of AccountDao .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM