使用静态吸气剂时,实例失去自动布线属性

问题描述:

我的Java类中有自动布线属性的问题。我有一个工厂,它有一个MyClass对象的Map<Integer, MyClass>。 MyClasses有一个projectId属性,这就是我希望从工厂获得它们的方式。但是,如果使用public static MyClassFactory getInstance()public MyClassInterface createMyClass,MyClasses中的自动装配属性在以这种方式检索时为null,但在插入到映射中时不为null。使用静态吸气剂时,实例失去自动布线属性

我想知道为什么发生这种情况以及如何避免这种情况。

除此之外,MyClass的范围设置为原型,但我不确定这是否能按照预期工作。任何想法,如果这项工作或如何执行这种行为?

@Configurable(preConstruction = true) 
public class MyClassFactory { 

    @Autowired 
    private BeanFactory beanFactory; 

    private static volatile MyClassFactory instance = null; 
    private final HashMap<Integer, MyClass> classMap; 

    private MyClassFactory() throws MyClassAlreadyRegisteredException { 
     this.classMap = new HashMap<Integer, MyClassInterface>(); 
     this.registerMyClasses(); 
    } 

    private void registerMyClasses() throws MyClassAlreadyRegisteredException { 
     registerMyClass(beanFactory.getBean(MyClass.class)); 
     registerMyClass(beanFactory.getBean(MyClass2.class)); 
     ... 
    } 

    private void registerMyClass(MyClassInterface myClassInterface) throws MyClassAlreadyRegisteredException { 
     for (int projectId : myClassInterface.getProjectIds()) { 
      if (classMap.containsKey(projectId)) { 
       throw new MyClassAlreadyRegisteredException(classMap.get(projectId).getClass().getName()); 
      } 
      classMap.put(projectId, myClassInterface); 
     } 
    } 

    public static MyClassFactory getInstance() throws MyClassAlreadyRegisteredException { 
     MyClassFactory result = instance; 
     if (result == null) { 
      synchronized (MyClassFactory.class) { 
       result = instance; 
       if (result == null) { 
        instance = result = new MyClassFactory(); 
       } 
      } 
     } 
     return result; 
    } 

    public MyClassInterface createMyClass(int projectId) throws NoMyClassRegisteredException, InstantiationException, 
      IllegalAccessException { 
     if (classMap.containsKey(projectId)) { 
      return classMap.get(projectId).create(); 
     } 
     throw new NoMyClassRegisteredException("for projectId: " + projectId); 
    } 

} 

(如果我没有把足够的信息在这里,请告诉我,我会增加更多。)

您在这里混合单春豆Singleton模式。你应该避免这一点。

编辑:

为什么你就不能使用它作为单春豆?:

@Configurable(preConstruction = true) 
public class MyClassFactory { 

    @Autowired 
    private BeanFactory beanFactory; 

    private final HashMap<Integer, MyClass> classMap; 

    @PostConstruct 
    private void init() throws MyClassAlreadyRegisteredException { 
     this.classMap = new HashMap<Integer, MyClassInterface>(); 
     this.registerMyClasses(); 
    } 

    private void registerMyClasses() throws MyClassAlreadyRegisteredException { 
     registerMyClass(beanFactory.getBean(MyClass.class)); 
     registerMyClass(beanFactory.getBean(MyClass2.class)); 
     ... 
    } 

    private void registerMyClass(MyClassInterface myClassInterface) throws MyClassAlreadyRegisteredException { 
     for (int projectId : myClassInterface.getProjectIds()) { 
      if (classMap.containsKey(projectId)) { 
       throw new MyClassAlreadyRegisteredException(classMap.get(projectId).getClass().getName()); 
      } 
      classMap.put(projectId, myClassInterface); 
     } 
    } 

    public MyClassInterface createMyClass(int projectId) throws NoMyClassRegisteredException, InstantiationException, 
      IllegalAccessException { 
     if (classMap.containsKey(projectId)) { 
      return classMap.get(projectId).create(); 
     } 
     throw new NoMyClassRegisteredException("for projectId: " + projectId); 
    } 

} 

而且比你可以自动装配这个bean到任何弹簧驱动类。 但是你的局部变量classMap仍然存在线程安全问题。你应该通过传递和摆脱中级课程来解决这个问题。如果你需要在singleton bean中缓存,你需要使它成为线程安全的。

+0

你能告诉我如何正确使用工厂吗? – DrunkenPope 2014-09-22 10:44:34