Interface BeanProvider

  • All Known Implementing Classes:
    CollectionBeanProvider, ConstantBeanProvider, ConstructorBeanProvider, FactoryBeanProvider, LifeCycleBeanProvider, ListBeanProvider, MapBeanProvider, MethodInvocationBeanProvider, PropertiesBeanProvider, SetBeanProvider, SimpleBeanProvider, SingletonBeanProvider

    public interface BeanProvider

    Definition of an interface for objects that provide access to beans.

    A bean is a plain old Java object that is somehow defined (e.g. its concrete class, some initialization properties, or some methods to be invoked). When the BeanProvider is asked for the bean it is responsible for, it has to ensure that it has been created and completely initialized. Then it can be handed over to the calling instance. It is up to a concrete implementation how this is achieved. One implementation can for instance always return the same bean instance, effectively implementing the singleton pattern. Another implementation could create a new bean instance on each request, which would be appropriate for a stateful service bean.

    The most interesting part of a bean provider is the fact that it can depend on other bean providers (which in turn can have dependencies on further providers and so on). These dependencies are dynamically resolved when a bean is requested, which can lead to a whole bunch of objects being created and initialized. The resulting bean is then fully initialized and ready for service. (These are the well-known concepts of dependency injection and inversion of control (IoC).

    The most important method of a BeanProvider is the getBean() method, which returns the fully initialized bean maintained by this provider. For the proper initialization of the bean and dynamic resolving of dependencies the getDependencies() method is also of importance.

    While providing a reference to the managed bean is naturally the main task of a bean provider, there are some other methods defined in this interface. These methods have a more technical background; they allow the dependency injection framework to effectively manage access to bean stores, especially if they are concurrently used by multiple threads. To better understand these methods some words about synchronization and threading issues are necessary:

    An access to the bean provided by a BeanProvider is automatically synchronized by the framework. This means that until the bean is completely created and initialized, no other thread can access this provider. If there are cyclic references in the dependency graph however (e.g. bean A depends on bean B, which depends on bean C, which again depends on bean A), the getBean() method can be entered again by the same thread. An implementation should be aware of this. The invocation of a bean provider's getBean() method is also called a transaction. If the bean store is concurrently accessed by other threads, it has to be ensured that the whole initialization process of a bean is not disturbed by other threads. The framework takes care about this. With the additional methods defined by this interface a BeanProvider implementation can obtain information about the start and the end of such transactions.

    When an application is about to shut down or when a BeanStore is closed, it is often necessary to do some clean up. For beans created by the framework - especially singleton service beans - it may be required to invoke a specific shutdown method, for instance if the bean is a database connection pool or something like that. For this purpose the BeanProvider interface defines the shutdown() method. Here a concrete implementation can place code for cleaning up the beans created by it.

    Version:
    $Id: BeanProvider.java 205 2012-01-29 18:29:57Z oheger $
    Author:
    Oliver Heger
    • Method Detail

      • getBean

        Object getBean​(DependencyProvider dependencyProvider)

        Returns the bean managed by this provider. This is the main method of a BeanProvider. A concrete implementation can do whatever is necessary to obtain the requested bean. Depending on the provider's semantic it can decide whether the bean is cached after it has been created, or whether for each request a new bean has to be created.

        The passed in reference to a DependencyProvider can be used for obtaining needed dependencies. This method will be automatically synchronized by the framework. However if there are cyclic dependencies, querying the DependencyProvider may cause the method to be entered again. An implementation must be aware of this to avoid endless loops.

        If a problem occurs when creating and initializing the bean, an implementation should throw a InjectionException exception.

        Parameters:
        dependencyProvider - the dependency provider
        Returns:
        the bean managed by this provider
      • getBeanClass

        Class<?> getBeanClass​(DependencyProvider dependencyProvider)
        Returns the class of the bean managed by this provider. Clients may query beans based on their class. So it becomes necessary to ask a provider for the bean class without having to create the bean first. A DependencyProvider is passed in that can be used for resolving the class (in case only the class name is known to the provider)
        Parameters:
        dependencyProvider - the dependency provider, which can be used for resolving the bean class
        Returns:
        the class of the bean managed by this provider
      • getDependencies

        Set<Dependency> getDependencies()
        Returns a set with the descriptions of the beans this provider depends on. These are typically beans the managed bean is to be initialized with through dependency injection. This method is called once by the framework whenever a transaction starts (i.e. when client code queries either this bean or a bean that depends on this provider). Its return value need not be constant over time (for instance a provider that always returns the same bean does not need any dependencies any more after the bean has been initialized on first access).
        Returns:
        a set with the dependency descriptions of the beans this bean provider depends on (can be null if there are no dependencies)
        See Also:
        Dependency
      • getLockID

        Long getLockID()
        Returns the ID of the transaction that locked this bean provider. A transaction locks each BeanProvider it depends on, so that it cannot be concurrently accessed by another thread. This is done using the setLockID(). An implementation will typically store the value passed in here and return it in getLockID(). However if a concrete implementation does not need any synchronization (e.g. because it only returns a constant object), it can always return null here.
        Returns:
        the ID of the locking transaction or null if there is none
      • setLockID

        void setLockID​(Long lid)
        Locks or unlocks this BeanProvider. This method is called with the ID of the current transaction to mark this provider as blocked. After that it cannot be accessed by a different thread until the locking transaction ends. Before it ends it will call this method again with a value of null. This method, in conjunction with the getLockID() method, is related to the implementation of synchronized access to bean providers. A BeanProvider implementation that requires synchronization should store the value passed in here in a member field and return it in the getLockID() method. An implementation that is thread-safe can leave this method empty and return always null in getLockID().
        Parameters:
        lid - the ID of the locking transaction
        See Also:
        getLockID()
      • isBeanAvailable

        boolean isBeanAvailable()
        Checks whether the bean managed by this provider can now be retrieved. This method can be used for detecting cyclic references: A bean may need other beans as arguments for its creation (e.g. for calling its constructor). This may cause the creation of these dependent beans. If one of these depends on the original bean, there is a cyclic dependency. Complex bean providers supporting enhanced bean creation and initialization should implement this method to return false if their managed bean is currently in the creation phase and thus does not really exist yet. A caller may then decide to try again later when the creation is complete. Simple bean providers can always return true.
        Returns:
        a flag whether the managed bean is available
      • shutdown

        void shutdown​(DependencyProvider dependencyProvider)
        Notifies this BeanProvider that it (and the bean(s) created by it) is no longer needed. A concrete implementation can use this method to perform some cleanup. It is also an opportunity for invoking a shutdown method on the bean created by this provider. Typically this method will be called when the BeanStore this BeanProvider belongs to is closed.
        Parameters:
        dependencyProvider - the DependencyProvider