Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring2.5中枚举和依赖项注入的映射_Java_Spring_Enums_Maps - Fatal编程技术网

Java Spring2.5中枚举和依赖项注入的映射

Java Spring2.5中枚举和依赖项注入的映射,java,spring,enums,maps,Java,Spring,Enums,Maps,假设我们有以下Java代码: public class Maintainer { private Map<Enum, List<Listener>> map; public Maintainer() { this.map = new java.util.ConcurrentHashMap<Enum, List<Listener>>(); } public void addListener( Listener

假设我们有以下Java代码:

public class Maintainer {
   private Map<Enum, List<Listener>> map;

   public Maintainer() {
      this.map = new java.util.ConcurrentHashMap<Enum, List<Listener>>();
   }

   public void addListener( Listener listener, Enum eventType ) {
      List<Listener> listeners;
      if( ( listeners = map.get( eventType ) ) == null ) {
         listeners = new java.util.concurrent.CopyOnWriteArrayList<Listener>();
         map.put( eventType, listeners );
      }
      listeners.add( listener );
   }
}
公共类维护器{
私人地图;
公共维护者(){
this.map=new java.util.ConcurrentHashMap();
}
public void addListener(侦听器侦听器,枚举事件类型){
列出听众名单;
if((侦听器=map.get(eventType))==null){
listeners=new java.util.concurrent.CopyOnWriteArrayList();
put(eventType,侦听器);
}
添加(侦听器);
}
}
这个代码片段不过是一个稍加改进的侦听器模式,其中每个侦听器都在告诉它感兴趣的事件类型,并且提供的方法维护这些关系的并发映射

最初,我希望通过我自己的注释框架调用此方法,但遇到了各种注释限制的障碍(例如,您不能将java.lang.Enum作为注释参数,还有一组各种类加载器问题),因此决定使用Spring

有人能告诉我怎么才能把这件事搞清楚吗?我想要实现的是:
1.将Maintainer类定义为Springbean。
2.通过使用addListener方法,使所有类型的侦听器都能够通过XML将自己注册到Maintainer。SpringDoc和Google在例子中都非常慷慨


有什么方法可以轻松做到这一点吗?

执行以下操作会有什么问题:

使用addListener(Listener,Enum)方法定义“Maintainer”接口

创建一个实现Maintainer的DefaultMaintainer类(如上所述)

然后,在每个侦听器类中,“注入”维护器接口(构造函数注入可能是一个不错的选择)。然后,侦听器可以向维护者注册自己

除此之外,我还不是100%清楚您目前在Spring方面的困难是什么!:)

您说过“…您不能将java.lang.Enum用作” 注释参数…”

我认为你错了。我最近在一个项目中使用了如下内容:

public @interface MyAnnotation {
    MyEnum value();
}
1) 将Maintainer类定义为Springbean

标准Spring语法适用于:

<bean id="maintainer" class="com.example.Maintainer"/>
但是,这很难实现,而且可能容易出错。我在一个项目上尝试了类似的方法,并创建了一个Spring实用程序类来提供帮助。目前我没有可用的源代码,因此我将描述如何实现我所做的

1) 将侦听的事件类型重构到
MyListener
接口中

public interface MyListener extends Listener {
  public Enum[] getEventTypes()
}
将注册方法更改为

public void addListener(MyListener listener)

2) 创建在上下文中查找所有相关侦听器的Spring helper类,并为找到的每个侦听器调用maintainer#addListener。我将从
BeanFilteringSupport
开始,并实现
BeanPostProcessor
(或
ApplicationListener
)在所有bean实例化后注册bean。

谢谢大家的回答。首先,快速跟进所有答案。
1.(alexvictor)是的,您可以使用具体的枚举作为注释参数,但不能使用java.lang.enum。
2.flicken提供的答案是正确的,但不幸的是有点吓人。我不是Spring专家,但这样做(创建方法以方便Spring访问)似乎有点过分,MethodInvokingFactoryBean解决方案也是如此。尽管我想对您的时间和努力表示衷心的感谢。
3.Phill的回答有点不寻常(不是注入侦听器bean,而是注入其维护者!),但是,我相信,这是所有可用方法中最干净的一种。我想我会沿着这条路走下去

再次感谢您的帮助。

有点离题(因为这不是关于Spring的),但在您的AddListener实现中有一个竞争条件:

  if( ( listeners = map.get( eventType ) ) == null ) {
     listeners = new java.util.concurrent.CopyOnWriteArrayList<Listener>();
     map.put( eventType, listeners );
  }
  listeners.add( listener );
if((侦听器=map.get(eventType))==null){
listeners=new java.util.concurrent.CopyOnWriteArrayList();
put(eventType,侦听器);
}
添加(侦听器);
如果两个线程同时调用此方法(对于以前没有侦听器的事件类型),map.get(eventType)将在两个线程中返回null,每个线程将创建自己的CopyOnWriteArrayList(每个线程包含一个侦听器),一个线程将替换另一个线程创建的列表,第一个侦听器将被遗忘

要解决此问题,请更改:

private Map<Enum, List<Listener>> map;

...

map.put( eventType, listeners );
私有地图;
...
put(eventType,侦听器);
致:

私有ConcurrentMap;
...
putIfAbsent(事件类型,侦听器);
侦听器=map.get(eventType);

嗯,这正是我所说的——“你不能将java.lang.Enum作为注释参数”。我在问春天我该怎么做?
private Map<Enum, List<Listener>> map;

...

map.put( eventType, listeners );
private ConcurrentMap<Enum, List<Listener>> map;

...

map.putIfAbsent( eventType, listeners );
listeners = map.get( eventType );