我的Java类中的自动装配属性存在问题。我有一个工厂,有Map<Integer, MyClass>
个MyClass对象。 MyClasses有一个projectId作为propterty,这就是我想从工厂获得它们的方式。但是当使用public static MyClassFactory getInstance()
和public MyClassInterface createMyClass
时,MyClasses中的自动装配属性在这样检索时为空,但在插入地图时不为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);
}
}
(如果我在这里没有提供足够的信息,请告诉我,我会添加更多信息。)
答案 0 :(得分:0)
你在这里混合Singleton模式和Spring单例bean。你应该避免这种情况。
编辑:
为什么不能将它用作Spring单例bean?:
@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自动装入任何Spring驱动的类中。 但是局部变量classMap仍存在线程安全问题。你应该通过传递它并摆脱中间类级别字段来解决这个问题。如果你需要在单例bean中使用缓存,你需要使它成为线程安全的。