Class SpringBeanClassBasedListenerObjectCreator

All Implemented Interfaces:
EventListener, ListenerObjectCreator, org.springframework.beans.factory.Aware, org.springframework.context.ApplicationContextAware, org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>

public class SpringBeanClassBasedListenerObjectCreator extends AbstractClassBasedListenerObjectCreator implements org.springframework.context.ApplicationContextAware, org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>
This ListenerObjectCreator creates ListenerObjects from classes. Users can pass in Classes or packagenames and this class will scan the Classes and create ListenerObjects for the public methods that are annotated with Listener. Note that public methods inherited from superclasses and superinterfaces will also be scanned. This means that users must take care not to scan a method twice, once as a method of a class and once as a method of a superclass, by passing a class/interface and its superclass/superinterface separately to this ListenerObjectCreator.

Please note that in Java, method annotations are NOT inherited. This means that, if you override/implement a method in a subclass or subinterface, and the overriding/implementing method does not have the annotation, then that method will not inherit it. If a class or interface just inherits a method, without overriding it, then the annotation WILL exist.

To get the actual Objects that the listeners run on, this will attempt to get a bean for a certain Class from the Spring Configuration. When no suitable bean can be found, the Class will simply be ignored.

When the classnames and/or packagenames are set, the classes/packagenames are accumulated into Collections, but actual processing of them will be done once the entire Spring Configuration is initialized. This is because this class needs other Spring Beans from the configuration to initialize the ListenerObjects.

By default, subpackages of packages are not scanned. This can be changed by using the setScanSubpackages(boolean) method.

NOTE: When using interface-based Spring Proxy's, you have to declare your Listener annotations on the interface-methods, not the class methods. RRiBbit does not even need to know about the implementing classes, it will simply ask Spring for a bean that implements the interface that the method is declared in.

Author:
G.J. Schouten
  • Field Details

    • classesToBeProcessed

      protected Collection<Class<?>> classesToBeProcessed
    • packageNamesToBeProcessed

      protected Collection<String> packageNamesToBeProcessed
    • classesToBeExcluded

      protected Collection<Class<?>> classesToBeExcluded
    • scanSubpackages

      protected boolean scanSubpackages
    • applicationContext

      protected org.springframework.context.ApplicationContext applicationContext
  • Constructor Details

    • SpringBeanClassBasedListenerObjectCreator

      public SpringBeanClassBasedListenerObjectCreator()
      Constructors of superclass are not copied, since that would make declaring a bean of this type in the Spring configuration quite verbose. Use the provided setters instead.
  • Method Details

    • setClassNames

      public void setClassNames(List<String> classNames)
      Set the classNames that are to be processed by calling AbstractClassBasedListenerObjectCreator.addClass(Class) once the Spring Configuration is initialized.
      Parameters:
      classNames -
    • setPackageNames

      public void setPackageNames(List<String> packageNames)
      Set the packageNames that are to be processed by calling AbstractClassBasedListenerObjectCreator.addPackage(String, boolean) once the Spring Configuration is initialized.
      Parameters:
      packageNames -
    • setExcludedClasses

      public void setExcludedClasses(Collection<Class<?>> excludedClasses)
      Sets the classes that should be exluced when the packages set with setPackageNames(List) are scanned.
      Parameters:
      excludedClasses -
    • setScanSubpackages

      public void setScanSubpackages(boolean scanSubpackages)
      Sets whether subpackages need to be scanned too. The default is false.
      Parameters:
      scanSubpackages -
    • getTargetObjectForClass

      protected Object getTargetObjectForClass(Class<?> clazz)
      Description copied from class: AbstractClassBasedListenerObjectCreator
      Gets a target execution Object for the given class to be used by a ListenerObject to execute its Method.
      Specified by:
      getTargetObjectForClass in class AbstractClassBasedListenerObjectCreator
      Parameters:
      clazz -
      Returns:
      an Object that has the type 'clazz' and can be used as an execution target, or 'null' if no such Object can be found
    • setApplicationContext

      public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext)
      Specified by:
      setApplicationContext in interface org.springframework.context.ApplicationContextAware
    • onApplicationEvent

      public void onApplicationEvent(org.springframework.context.event.ContextRefreshedEvent contextRefreshedEvent)
      When the Spring Configuration is reloaded, all ListenerObjects contained in this ListenerObjectCreator are dropped, and new ones are created from the classNames and packageNames set in this bean. This means that if you added listeners to this object with one of the methods of one of the superclasses, such as AbstractClassBasedListenerObjectCreator.addClass(Class), ObjectBasedListenerObjectCreator.addObject(Object) or AbstractClassBasedListenerObjectCreator.addPackage(String, boolean), all the ListenerObjects that resulted from those calls will no longer be there after this call.

      This is by design. The reason for doing this is because a ContextRefreshedEvent represents a total refresh of all objects in the application, erasing previous state. If you do not want this, you can extend this class and override the three mentioned add* methods. Each of them must then add the Classes and packageNames it processes to the Collections in this object, before calling super.

      Specified by:
      onApplicationEvent in interface org.springframework.context.ApplicationListener<org.springframework.context.event.ContextRefreshedEvent>
      Parameters:
      contextRefreshedEvent -