Singleton 和 @Autowired 返回 NULL

发布于 2024-10-17 13:52:45 字数 4024 浏览 8 评论 0原文

我有一个存储库管理器来管理我的存储库。我有 @Autowired 来实例化我的属性,但它们始终为空。 bean 在我的 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;
        }
    }

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>

用户存储库.java

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

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

I have a repository manager that manages my repositories. I have the @Autowired to instantiate my properties, but they are always null. The beans are correctly configured in my xml. Any reason why?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

活雷疯 2024-10-24 13:52:45

我自己也遇到过这个。问题是,当您

new RepositoryManager();

在 Instance() 中执行操作时,您没有使用 Spring 来创建 RepositoryManager,因此您的实例不会发生依赖项注入(没有自动装配)。

解决方案是取消 Instance() 单例模式。如果你想坚持使用单例,那么就这样做

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

然后无论你在哪里需要存储库管理器,只需自动装配对它的引用(假设调用bean也由Spring管理!)

@Autowired
private RepositoryManager repositoryManager = null;

I just ran into this myself. The problem is that when you do

new RepositoryManager();

in Instance(), you are not using Spring to create RepositoryManager, and thus the dependency injection isn't happening for your instance (no autowiring).

The solution is to do away with the Instance() singleton pattern. If you want to insist on a Singleton, then do this

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

Then wherever you need the repository manager, just autowire in a reference to it (assuming the calling bean is also managed by Spring!)

@Autowired
private RepositoryManager repositoryManager = null;
断肠人 2024-10-24 13:52:45

请确保您的配置中有以下内容:

<context:annotation-config />

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

如果有,请发布您的配置 xml

Please make sure that you have the following in your config:

<context:annotation-config />

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

If you have it then post your configuration xml

舞袖。长 2024-10-24 13:52:45

实际上有一种非常优雅的方法可以鱼与熊掌兼得,即拥有一个同样由 Spring 管理的 JVM 单例。假设您有一个带有自动装配 bean 的纯 java 单例,如下所示:

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 单例 bean 的典型问题的“修复”,这些 bean 不是真正的 JVM 单例,因为它们是由 Spring 实例化的。使用上面的模式可以强制执行 JVM 级别的单例,即编译器强制执行的单例以及容器单例。

There is actually a very elegant way to have your cake and eat it, i.e., have a JVM singleton that's also Spring-managed. Say you have a pure java singleton with an autowired bean like this:

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
}

You can force Spring to manage this singleton simply by adding in your application context the following line:

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

Now your singleton will have an instance of SomeSpringBean autowired (if available in the context).

Moreover, this is a 'fix' for the typical problem with Spring singleton beans that are not truly JVM singletons because they get instantiated by Spring. Using the pattern above enforces JVM level singleton, i.e., compiler enforced singleton, together with container singleton.

初见 2024-10-24 13:52:45

发生这种情况的原因是

您在 spring 上下文之外创建 POJO 的静态方法 Instance() 。

您可以通过将 添加到您的配置中来解决此问题,然后使用 @Configurable 注释 RepositoryManager

The reason this is happening is because of the static method Instance()

you are creating the POJO outside of the spring context.

you can fix this, by adding <context:spring-configured /> to your configuration, and then annotating RepositoryManager with @Configurable

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文