Синглтон и @Autowired возвращают NULL

У меня есть менеджер репозитория, который управляет моими репозиториями. У меня есть @Autowired для создания экземпляров моих свойств, но они всегда равны нулю. Компоненты правильно настроены в моем xml. Любая причина, почему?

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

дао.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);
    }

person Mike Flynn    schedule 15.02.2011    source источник
comment
Если бы бины были настроены правильно, ваши поля не были бы нулевыми. Покажи конфиг.   -  person skaffman    schedule 16.02.2011
comment
Я добавил репозиторий xml и примеров. Тот же самый репозиторий можно внедрить вручную, поскольку он является свойством контроллера, но в этом статическом методе он не заполняется.   -  person Mike Flynn    schedule 16.02.2011
comment
(a) Почему RepositoryManager управляет своим синглтоном? (b) Где RepositoryManager определяется в Spring? В каком он пакете? (c) Почему вы объявляете явные bean-компоненты репозитория, когда вы уже объявили компонентное сканирование?   -  person skaffman    schedule 16.02.2011
comment
a.) Исправлен синтаксис singleton b.) Я добавил @Component в RepositoryManager, и он находится в пакете com.cisco.badges.data.repositories; c.) Я удалил их из xml и просто использую аннотации. Происходит то же самое.   -  person Mike Flynn    schedule 16.02.2011


Ответы (4)


Я просто столкнулся с этим сам. Проблема в том, что когда вы делаете

new RepositoryManager();

в Instance() вы не используете Spring для создания RepositoryManager, и поэтому внедрение зависимостей не происходит для вашего экземпляра (без автоматического подключения).

Решение состоит в том, чтобы покончить с одноэлементным шаблоном Instance(). Если вы хотите настаивать на синглтоне, сделайте это

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

Затем, где бы вам ни понадобился менеджер репозитория, просто автоматически подключите ссылку на него (при условии, что вызывающий компонент также управляется Spring!)

@Autowired
private RepositoryManager repositoryManager = null;
person werkshy    schedule 29.09.2011

Пожалуйста, убедитесь, что в вашей конфигурации есть следующее:

<context:annotation-config />

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

Если он у вас есть, опубликуйте свою конфигурацию xml

person danny.lesnik    schedule 15.02.2011
comment
У меня есть аннотации, а сканирование компонентов - person Mike Flynn; 16.02.2011
comment
Я думаю, вам также нужен ‹context:annotation-config /›, пожалуйста, посмотрите на этот пример mkyong.com/spring/, и я также смотрю на свой код и вижу его там. - person danny.lesnik; 16.02.2011
comment
То же самое. Я думаю, это связано с его синглтонной частью? - person Mike Flynn; 16.02.2011
comment
Может быть, вы можете ответить на вопросы @skaffman? в любом случае это очень интересный вопрос. - person danny.lesnik; 16.02.2011

На самом деле существует очень элегантный способ получить свой пирог и съесть его, т. Е. Иметь синглтон JVM, который также управляется Spring. Скажем, у вас есть чистый java-синглтон с автосвязанным bean-компонентом, например:

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
}

Вы можете заставить Spring управлять этим синглтоном, просто добавив в контекст вашего приложения следующую строку:

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

Теперь у вашего синглтона будет экземпляр SomeSpringBean с автоматическим подключением (если он доступен в контексте).

Кроме того, это «исправление» для типичной проблемы с одиночными компонентами Spring, которые не являются настоящими синглтонами JVM, потому что они создаются Spring. Использование приведенного выше шаблона обеспечивает одноэлементный уровень JVM, т. Е. Одноэлементный принудительный компилятор, вместе с одноэлементным контейнером.

person Giovanni Botta    schedule 20.09.2013

Это происходит из-за статического метода Instance()

вы создаете POJO вне контекста Spring.

вы можете исправить это, добавив <context:spring-configured /> в свою конфигурацию, а затем аннотировав RepositoryManager с помощью @Configurable

person kabal    schedule 05.06.2012