public SingleArgumentMethodEventListener(Object target, Method method) { this.target = target; this.method = method; //assert that the method is defined as expected: getMethodArgumentType(method); assertPublicMethod(method); }
protected EventBus eventBus() { return new DefaultEventBus(); }
public Class getEventType() { return getMethodArgumentType(getMethod()); }
public void register(Object instance) { if (instance == null) { log.info("Received null instance for event listener registration. Ignoring registration request."); return; } unregister(instance); List<EventListener> listeners = getEventListenerResolver().getEventListeners(instance); if (listeners == null || listeners.isEmpty()) { log.warn("Unable to resolve event listeners for subscriber instance [{}]. Ignoring registration request.", instance); return; } Subscription subscription = new Subscription(listeners); this.registryWriteLock.lock(); try { this.registry.put(instance, subscription); } finally { this.registryWriteLock.unlock(); } }
public void onEvent(Object event) { Set<Object> delivered = new HashSet<Object>(); for (EventListener listener : this.listeners) { Object target = listener; if (listener instanceof SingleArgumentMethodEventListener) { SingleArgumentMethodEventListener singleArgListener = (SingleArgumentMethodEventListener) listener; target = singleArgListener.getTarget(); } if (listener.accepts(event) && !delivered.contains(target)) { try { listener.onEvent(event); } catch (Throwable t) { log.warn(EVENT_LISTENER_ERROR_MSG, t); } delivered.add(target); } } } }
public int compare(EventListener a, EventListener b) { if (a == null) { if (b == null) { return 0; } else { return -1; } } else if (b == null) { return 1; } else if (a == b || a.equals(b)) { return 0; } else { if (a instanceof TypedEventListener) { TypedEventListener ta = (TypedEventListener)a; if (b instanceof TypedEventListener) { TypedEventListener tb = (TypedEventListener)b; return EVENT_CLASS_COMPARATOR.compare(ta.getEventType(), tb.getEventType()); } else { return -1; //TypedEventListeners are 'less than' (higher priority) than non typed } } else { if (b instanceof TypedEventListener) { return 1; } else { return 0; } } } } }
/** * Returns a new collection of {@link EventListener} instances, each instance corresponding to an annotated * method discovered on the specified {@code instance} argument. * * @param instance the instance to inspect for annotated event handler methods. * @return a new collection of {@link EventListener} instances, each instance corresponding to an annotated * method discovered on the specified {@code instance} argument. */ public List<EventListener> getEventListeners(Object instance) { if (instance == null) { return Collections.emptyList(); } List<Method> methods = ClassUtils.getAnnotatedMethods(instance.getClass(), getAnnotationClass()); if (methods == null || methods.isEmpty()) { return Collections.emptyList(); } List<EventListener> listeners = new ArrayList<EventListener>(methods.size()); for (Method m : methods) { listeners.add(new SingleArgumentMethodEventListener(instance, m)); } return listeners; }
public boolean accepts(Object event) { return event != null && getEventType().isInstance(event); }
public DefaultEventBus() { this.registry = new LinkedHashMap<Object, Subscription>(); //not thread safe, so we need locks: ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); this.registryReadLock = rwl.readLock(); this.registryWriteLock = rwl.writeLock(); this.eventListenerResolver = new AnnotationEventListenerResolver(); }
public void publish(Object event) { if (event == null) { log.info("Received null event for publishing. Ignoring and returning."); return; } registryReadLock.lock(); try { //performing the entire iteration within the lock will be a slow operation if the registry has a lot of //contention. However, it is expected that the very large majority of cases the registry will be //read-mostly with very little writes (registrations or removals) occurring during a typical application //lifetime. // //The alternative would be to copy the registry.values() collection to a new LinkedHashSet within the lock //only and the iteration on this new collection could be outside the lock. This has the performance penalty //however of always creating a new collection every time an event is published, which could be more //costly for the majority of applications, especially if the number of listeners is large. // //Finally, the read lock is re-entrant, so multiple publish calls will be //concurrent without penalty since publishing is a read-only operation on the registry. for (Subscription subscription : this.registry.values()) { subscription.onEvent(event); } } finally { registryReadLock.unlock(); } }
private Map<String,Object> createDefaultObjectMap() { Map<String,Object> map = new LinkedHashMap<String, Object>(); map.put(EVENT_BUS_NAME, new DefaultEventBus()); return map; }
/** * Default no-arg constructor that will automatically attempt to initialize a default cacheManager */ public CachingSecurityManager() { //use a default event bus: setEventBus(new DefaultEventBus()); }
/** * Destroys the {@link #getCacheManager() cacheManager} via {@link LifecycleUtils#destroy LifecycleUtils.destroy}. */ public void destroy() { LifecycleUtils.destroy(getCacheManager()); this.cacheManager = null; LifecycleUtils.destroy(getEventBus()); this.eventBus = new DefaultEventBus(); }
/** * Default no-arg constructor that will automatically attempt to initialize a default cacheManager */ public CachingSecurityManager() { //use a default event bus: setEventBus(new DefaultEventBus()); }
/** * Destroys the {@link #getCacheManager() cacheManager} via {@link LifecycleUtils#destroy LifecycleUtils.destroy}. */ public void destroy() { LifecycleUtils.destroy(getCacheManager()); this.cacheManager = null; LifecycleUtils.destroy(getEventBus()); this.eventBus = new DefaultEventBus(); }
protected EventBus eventBus() { return new DefaultEventBus(); }
private Map<String,Object> createDefaultObjectMap() { Map<String,Object> map = new LinkedHashMap<String, Object>(); map.put(EVENT_BUS_NAME, new DefaultEventBus()); return map; }