10 votes

Singleton et @Autowired retournant NULL

J'ai un gestionnaire de référentiel qui gère mes référentiels. J'ai le @Autowired pour instancier mes propriétés, mais elles sont toujours nulles. Les beans sont correctement configurés dans mon xml. Quelle en est la raison ?

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);
    }

22voto

werkshy Points 542

Je viens de rencontrer ce problème moi-même. Le problème est que lorsque vous faites

new RepositoryManager();

dans Instance(), vous n'utilisez pas Spring pour créer RepositoryManager, et donc l'injection de dépendance ne se produit pas pour votre instance (pas d'autowiring).

La solution consiste à supprimer le modèle de singleton Instance(). Si vous voulez insister sur un singleton, faites ceci

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

Ensuite, chaque fois que vous avez besoin du gestionnaire de référentiel, il suffit d'insérer une référence à celui-ci (en supposant que le bean appelant est également géré par Spring !)

@Autowired
private RepositoryManager repositoryManager = null;

5voto

danny.lesnik Points 9526

Veuillez vous assurer que vous avez les éléments suivants dans votre configuration :

<context:annotation-config />

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

Si vous l'avez, postez votre configuration xml.

5voto

Giovanni Botta Points 2674

Il existe en fait un moyen très élégant d'avoir le beurre et l'argent du beurre, c'est-à-dire d'avoir une JVM singleton qui est également gérée par Spring. Disons que vous avez un singleton java pur avec un bean autowired comme ceci :

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
}

Vous pouvez forcer Spring à gérer ce singleton simplement en ajoutant dans votre contexte d'application la ligne suivante :

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

Maintenant, votre singleton aura une instance de SomeSpringBean auto-connecté (si disponible dans le contexte).

De plus, il s'agit d'un "correctif" pour le problème typique des beans singleton de Spring qui ne sont pas vraiment des singletons JVM car ils sont instanciés par Spring. L'utilisation du modèle ci-dessus renforce le singleton au niveau de la JVM, c'est-à-dire le singleton imposé par le compilateur, ainsi que le singleton du conteneur.

0voto

kabal Points 454

La raison pour laquelle cela se produit est due à la méthode statique Instance()

vous créez le POJO en dehors du contexte de Spring.

vous pouvez corriger cela en ajoutant <context:spring-configured /> à votre configuration, puis en annotant RepositoryManager con @Configurable

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X