2011-02-15 15 views
9

Tengo un administrador de repositorio que administra mis repositorios. Tengo @Autowired para crear instancias de mis propiedades, pero siempre son nulas. Los beans están configurados correctamente en mi xml. ¿Alguna razón por qué?Singleton y @Autowired return NULL

public class RepositoryManager { 

     private static RepositoryManager instance; 

     private RepositoryManager() 
     { 
     } 

     public static RepositoryManager Instance() 
     { 
      if(instance == null) 
       instance = new RepositoryManager(); 

      return instance; 
     } 

     @Autowired 
     private IUserRepository userRepository; 

     @Autowired 
     private IRoleRepository roleRepository; 

     @Autowired 
     private IAssetRepository assetRepository; 

     public IUserRepository getUserRepository() { 
      return userRepository; 
     } 

     public void setUserRepository(IUserRepository userRepository) { 
      this.userRepository = userRepository; 
     } 

     public IRoleRepository getRoleReposttory() { 
      return roleRepository; 
     } 

     public void setRoleReposttory(IRoleRepository roleRepository) { 
      this.roleRepository = roleRepository; 
     } 

     public IAssetRepository getAssetRepository() { 
      return assetRepository; 
     } 

     public void setAssetRepository(IAssetRepository assetRepository) { 
      this.assetRepository = assetRepository; 
     } 
    } 

dao.xml

<!-- Scans within the base package of the application for @Components to configure as beans --> 
    <context:component-scan base-package="com.cisco.badges.data.*" /> 

    <context:property-placeholder location="classpath:jdbc.properties"/> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
     <property name="driverClassName" value="${jdbc.driverClassName}"/> 
     <property name="url" value="${jdbc.url}"/> 
     <property name="username" value="${jdbc.username}"/> 
     <property name="password" value="${jdbc.password}"/> 
     </bean> 

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/> 
     <property name="annotatedClasses"> 
      <list> 
       <value>com.cisco.badges.data.domain.User</value> 
       <value>com.cisco.badges.data.domain.Role</value> 
       <value>com.cisco.badges.data.domain.Asset</value> 
       <value>com.cisco.badges.data.domain.UserRole</value> 
       <value>com.cisco.badges.data.domain.UserRole$UserRolePK</value> 
       <value>com.cisco.badges.data.domain.UserAsset</value> 
       <value>com.cisco.badges.data.domain.UserAsset$UserAssetPK</value> 
      </list> 
     </property> 
     <property name="configLocation"> 
      <value>classpath:hibernate.cfg.xml</value> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.format_sql">true</prop> 
      </props> 
     </property> 
    </bean> 

    <tx:annotation-driven/> 

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

</beans> 

userrepository.java

@Repository("userRepository") 
public class UserRepository extends 
     BaseRepository<User, Long> implements 
     IUserRepository { 

    @Autowired 
    public UserRepository(SessionFactory sessionFactory) { 
     super(sessionFactory); 
    } 
+0

Si los beans * fueron * configurados correctamente, sus campos no serían nulos. Muéstranos la configuración. – skaffman

+0

Agregué el xml y el repositorio de muestra. El mismo repositorio se puede inyectar manualmente siendo una propiedad en un controlador, pero dentro de este método estático no se está llenando. –

+0

(a) ¿Por qué 'RepositoryManager' administra su propio singleton? (b) ¿Dónde se define 'RepositoryManager' en Spring? ¿En qué paquete está? (c) ¿Por qué declaras beans de repositorio explícitos cuando ya has declarado un componente escaneo? – skaffman

Respuesta

5

Por favor asegúrese de que usted tiene lo siguiente en su fichero de configuración:

<context:annotation-config /> 

<context:component-scan base-package="name.of.your.package"></context:component-scan> 

Si lo tienes luego publique su configuración xml

+0

Tengo una anotación, y la exploración de componente –

+0

Creo que necesita , también mire este ejemplo http://www.mkyong.com/spring/spring-auto-wiring- beans-with-autowired-annotation/y también estoy mirando mi código y lo veo allí. –

+0

Lo mismo. Creo que tiene que ver con la parte singleton de esto? –

21

Me encontré con esto yo mismo. El problema es que cuando se hace

new RepositoryManager(); 

en Instancia(), que no está utilizando la primavera para crear RepositoryManager, y por tanto la inyección de dependencia no está sucediendo para la instancia (sin autowiring).

La solución es eliminar el patrón singleton de Instancia(). Si desea insistir en un Singleton, a continuación, hacer esto

@Component 
@Scope(value = "singleton") 
public class RepositoryManager { 
    ... 
} 

A continuación, siempre que se necesite el gerente repositorio, simplemente Autowire en una referencia a él (suponiendo que el frijol llamar también es administrado por la primavera!)

@Autowired 
private RepositoryManager repositoryManager = null; 
+0

+1 Buen disparo. Gracias. –

0

la razón de que esto está sucediendo es por el método estático Instance()

está creando el POJO fuera del contexto de la primavera.

se puede solucionar este problema, mediante la adición de <context:spring-configured /> a su configuración, y luego anotar RepositoryManager con @Configurable

3

realidad, hay una manera muy elegante de tener su pastel y comerlo, es decir, tener un producto único JVM que también es primavera administrado Digamos que usted tiene un producto único java puro con un bean autowired así:

public final class MySingletonClass{ 
    private static MySingletonClass instance; 

    public static MySingletonClass getInstance(){ 
    if(instance==null){ 
     synchronized{ 
     if(instance==null){ 
      instance = new MySingletonClass(); 
     } 
     } 
    } 
    return instance; 
    } 

    @Autowired 
    private SomeSpringBean bean; 

    // other singleton methods omitted 
} 

Puede forzar la primavera para gestionar este Singleton simplemente añadiendo en su contexto de aplicación la siguiente línea:

<bean class="com.mypackage.MySingletonClass" factory-method="getInstance"/> 

Ahora su Singleton tendrá una instancia de SomeSpringBean autocableada (si está disponible en el contexto).

Además, esta es una "solución" para el problema típico con los beans de Singleton de Spring que no son realmente singleton de JVM porque Spring lo ha instanciado. Al utilizar el patrón anterior, se aplica el singleton de nivel de JVM, es decir, el singleton forzado por el compilador, junto con el singleton del contenedor.

Cuestiones relacionadas