让我们假设我们已经得到了下列代码:

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

这段代码是什么但有一点改善监听的模式,其中每个监听说是什么类型的事件很感兴趣,并提供方法保持一个并发的地图,这些关系。

起初,我想这种方法是通过我自己的注释框架,但是撞到砖墙的各种注释的限制(例如你不能拥有 java。郎。Enum 如注释的参数,还有一个集中的各类装入器问题),因此决定使用弹簧。

谁能告诉我怎么做我Spring_ify_这个吗?什么我想要实现的是:
1.定义 维护者 类作为春季豆。
2.让它使各种各样的听众能够注册自己 维护者 通过XML的采用 addListener 法。弹簧医生,也没有谷歌都是很慷慨的例子。

有没有办法实现这很容易吗?

有帮助吗?

解决方案

会是什么错误的做喜欢的东西如下:

定义的'维护者'接口与addListener(Listener,Enum)的方法。

创建一个DefaultMaintainer类(如上),实现维护者。

然后,在每个监听器类,注入'维护者的接口(constructor注可能是一个好的选择)。听众可以那么登记册本身的维护者。

另外,我不是100%清楚到底是什么你的困难是与春天的时刻!:)

其他提示

稍offtopic(因为这不是关于春天),但有一个竞争条件在您的执行情况的AddListener:

  if( ( listeners = map.get( eventType ) ) == null ) {
     listeners = new java.util.concurrent.CopyOnWriteArrayList<Listener>();
     map.put( eventType, listeners );
  }
  listeners.add( listener );

如果两个线电话这种方法在同一时间(一个事件的类型,以前有没有听众),地图。获得(eventType)将返回null在线,每个线程将创建自己的CopyOnWriteArrayList(每个含有一个单一的监听),一个线程将取代表创建的通过其他,第一个监听器会被遗忘。

为了解决这个问题,改变:

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

...

map.put( eventType, listeners );

为:

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

...

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

1)定义的维护者类作为春季豆。

标准的弹簧法适用于:

<bean id="maintainer" class="com.example.Maintainer"/>

2)使所有各种各样的听众能够自己注册来维护者通过XML通过使用addListener方法。弹簧医生,也没有谷歌都是很慷慨的例子。

这是棘手。你的 可能 使用 MethodInvokingFactoryBean 单独通话 maintainer#addListener, 是这样的:

<bean id="listener" class="com.example.Listener"/>

<bean id="maintainer.addListener" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
  <property name="targetObject" ref="maintainer"/>
  <property name="targetMethod" value="addListener"/>
  <property name="arguments">
    <list>
      <ref>listener</ref>
      <value>com.example.MyEnum</value>
   </list>
 </property>
</bean>

然而,这是笨重的,并且可能容易出错。我尝试类似的一个项目,并且创建了一个弹簧用类帮助,而不是。我没有的源代码可用的时刻,所以我将描述如何实现我做了什么。

1)"重构"的活动类型听到 MyListener 接口

public interface MyListener extends Listener {
  public Enum[] getEventTypes()
}

这改变的登记方法

public void addListener(MyListener listener)

2)创建春助手类,认定所有相关的听众在这方面,并呼吁维护者#addListener为每个监听发现。我会开始 BeanFilteringSupport, ,并且还实施 BeanPostProcessor (或 ApplicationListener)注册的豆后所有豆子已经被初始化。

你说"...你不能拥有java。郎。Enum为" 注param..."

我认为你是错误的。我最近使用的一个项目是这样的:

public @interface MyAnnotation {
    MyEnum value();
}

谢谢你所有的答案。第一,一个快速跟踪所有的答案。
1.(alexvictor)是的,你可以有具体的 enum 如注释的参数,但不是 java。郎。Enum.
2.回答提供flicken是正确的,但不幸的是有点吓人。我不是春天的专家,但做的事情,这种方法(创建方法更容易春天访问),这似乎是一位矫枉过正,为的是 MethodInvokingFactoryBean 解决方案。虽然我想表达我的真诚感谢您的时间和精力。
3.答案由菲尔是一位不同寻常(而不是注射侦听豆,注入它的维护者!), 但是,我相信,最干净的所有可用的。我想我会走这条道路。

再次,非常感谢你对你有所帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top