Java Spring2.5中枚举和依赖项注入的映射
假设我们有以下Java代码: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
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 );