[英]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.