簡體   English   中英

Spring @Autowired在@Repository bean中為null

[英]Spring @Autowired gives null in a @Repository bean

我有一個使用@Autowired注入SessionFactory的簡單獨立應用程序,下面是代碼:

package au.edu.rdsi.rexportal;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.GenericXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository("rexportalConsole")
public class RexportalConsole {
    @Autowired
    private SessionFactory sessionFactory;

    public static void main(String[] args) {
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
        ctx.getEnvironment().setActiveProfiles("development");
        ctx.load("classpath:META-INF/spring-rexportal.xml");
        ctx.refresh();
        RexportalConsole rc = (RexportalConsole) ctx.getBean("rexportalConsole");
        System.out.println(rc);
        System.out.println(rc.sessionFactory);
    }

}

當我運行該程序時,sessionFactory屬性始終為null:

au.edu.rdsi.rexportal.RexportalConsole@1f3a1de9
null

但是,如果我將@Repository更改為@Component,則會得到正確的結果,並且可以使用sessionFactory bean:

au.edu.rdsi.rexportal.RexportalConsole@14eb7ad0
org.hibernate.impl.SessionFactoryImpl@6fcbf86a

我想使用@Repository,因為我需要翻譯異常,正如您在application.xml中看到的那樣,PersistenceExceptionTranslationPostProcessor適用於@Respository:

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

<context:component-scan base-package="au.edu.rdsi.rexportal" />

<context:annotation-config />

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

<beans profile="production, qa, staging">
    <jee:jndi-lookup id="rexportalDS" jndi-name="java:jboss/datasources/rexportalDS" />
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="rexportalDS" />
        <property name="mappingLocations" value="classpath:au/edu/rdsi/rexportal/domain/**/*.hbm.xml" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
            </props>
        </property>
    </bean>
</beans>

<beans profile="development, test">
    <bean id="rexportalDS" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/rexportal" />
        <property name="username" value="password" />
        <property name="password" value="password" />
        <property name="initialSize" value="5" />
        <property name="maxActive" value="10" />
    </bean>
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="rexportalDS" />
        <property name="mappingLocations" value="classpath:au/edu/rdsi/rexportal/domain/**/*.hbm.xml" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true"</prop>
            </props>
        </property>
    </bean>
</beans>

我想念什么嗎? 為什么@Component在這里工作,但@Respository在這里?

這是我使用@Repository時的日志:

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [META-INF/spring-rexportal.xml]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@6f3a342a: startup date [Sun Apr 13 00:31:30 EST 2014]; root of context hierarchy
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
INFO : org.springframework.context.support.GenericXmlApplicationContext - Bean 'rexportalDS' of type [class org.apache.commons.dbcp.BasicDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO : org.springframework.context.support.GenericXmlApplicationContext - Bean 'sessionFactory' of type [class org.springframework.orm.hibernate3.LocalSessionFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@37cae761: defining beans [messageDao,rexportalConsole,messageService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,rexportalDS,sessionFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
au.edu.rdsi.rexportal.RexportalConsole@3a3248be
null
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@6f3a342a: startup date [Sun Apr 13 00:31:30 EST 2014]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@37cae761: defining beans [messageDao,rexportalConsole,messageService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,rexportalDS,sessionFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy

並在使用@Component時記錄日志:

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [META-INF/spring-rexportal.xml]
INFO : org.springframework.context.support.GenericXmlApplicationContext - Refreshing org.springframework.context.support.GenericXmlApplicationContext@2c683bfc: startup date [Sun Apr 13 00:42:43 EST 2014]; root of context hierarchy
INFO : org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
INFO : org.springframework.context.support.GenericXmlApplicationContext - Bean 'rexportalDS' of type [class org.apache.commons.dbcp.BasicDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO : org.springframework.context.support.GenericXmlApplicationContext - Bean 'sessionFactory' of type [class org.springframework.orm.hibernate3.LocalSessionFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3d600a0c: defining beans [messageDao,rexportalConsole,messageService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,rexportalDS,sessionFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
au.edu.rdsi.rexportal.RexportalConsole@26d6221b
org.hibernate.impl.SessionFactoryImpl@34592e88
INFO : org.springframework.context.support.GenericXmlApplicationContext - Closing org.springframework.context.support.GenericXmlApplicationContext@2c683bfc: startup date [Sun Apr 13 00:42:43 EST 2014]; root of context hierarchy
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3d600a0c: defining beans [messageDao,rexportalConsole,messageService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,rexportalDS,sessionFactory,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy

當異常轉換代理包裝rexportalConsole bean時,該字段訪問中斷。 否則,@ @Autowired會變得不合適。

看看這個

@Component
//@Repository
public class RexportalConsole {
    @Autowired
    private SessionFactory sessionFactory;

    @PostConstruct
    public void foo() {
        System.out.println("postconstruct this:" + this);
        System.out.println("postconstruct this.sessionFactory:" + this.sessionFactory);
    }

    public static void main(String[] args) throws InterruptedException {
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
        ctx.getEnvironment().setActiveProfiles("development");
        ctx.load("classpath:META-INF/spring-rexportal.xml");
        ctx.refresh();
        RexportalConsole rc = (RexportalConsole) ctx.getBean("rexportalConsole");
        System.out.println("main rc:" + rc);
        System.out.println("main rc.sessionFactory:" + rc.sessionFactory);
        System.out.println("main rc.getSessionFactory():" + rc.getSessionFactory());
        // rc.fail();
    }


    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }


    public void fail() {
        throw new SQLGrammarException("foo",null);
    }
}

產生

postconstruct this:au.edu.rdsi.rexportal.RexportalConsole@7e3e1a61
postconstruct this.sessionFactory:org.hibernate.impl.SessionFactoryImpl@1f361707
main rc:au.edu.rdsi.rexportal.RexportalConsole@7e3e1a61
main rc.sessionFactory:org.hibernate.impl.SessionFactoryImpl@1f361707
main rc.getSessionFactory():org.hibernate.impl.SessionFactoryImpl@1f361707

交換注釋以使用@Repository會產生此結果

postconstruct this:au.edu.rdsi.rexportal.RexportalConsole@79e893ae
postconstruct this.sessionFactory:org.hibernate.impl.SessionFactoryImpl@1437c309
main rc:au.edu.rdsi.rexportal.RexportalConsole@79e893ae
main rc.sessionFactory:null
main rc.getSessionFactory():org.hibernate.impl.SessionFactoryImpl@1437c309

對於這種情況為什么會發生,我可能會有些明顯的遺漏,例如代理正在代理getter方法,並且在直接字段訪問時只返回null,但是我必須深入研究原因。

無論如何,您的接線確實有效。

更新 :另一個答案表明PersistenceExceptionTranslationPostProcessor是多余的。 事實並非如此。 如果取消注釋上面代碼中的rc.fail()行,則在注釋掉PostProcessor bean時將看到一個Hibernate SQLGrammarException ,而在包含它時將看到一個Spring InvalidDataAccessResourceUsageException 僅在聲明了PostProcessor情況下,才會創建包裝@Repository並進行異常轉換的代理。 就是通過隱藏字段來破壞字段訪問的是該代理。 您可以在第14.2.2節的手冊中閱讀有關內容。

嘗試如下自動裝配會話工廠:

private SessionFactory sessionFactory;

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM