public interface

FeatureSpecification

org.springframework.context.config.FeatureSpecification
Known Indirect Subclasses

Class Overview

Interface to be implemented by objects that specify the configuration of a particular feature of the Spring container e.g., component-scanning, JMX MBean exporting, AspectJ auto-proxying, annotation-driven transaction management, and so on.

Many features of the Spring container can be configured using either XML or annotations. As one example, Spring's component scanning feature may be configured using either the <context:component-scan> XML element or (as of Spring 3.1) the @ComponentScan annotation. These two options are equivalent to one another, and users may choose between them as a matter of convention or preference. Fundamentally, both are declarative mechanisms for specifying how the Spring container should be configured. A FeatureSpecification object, then, is a way of representing this configuration information independent of its original source format be it XML, annotations, or otherwise.

A FeatureSpecification is responsible for validating itself. For example, a component-scanning specification would check that at least one base package has been specified, and otherwise register a Problem with a ProblemReporter. Taking this approach as opposed to throwing exceptions allows for maximum tooling and error reporting flexibility.

A FeatureSpecificationExecutor is used to carry out the instructions within a populated FeatureSpecification; this is where the "real work" happens. In the case of component scanning as above, it is within a FeatureSpecificationExecutor that a bean definition scanner is created, configured and invoked against the base packages specified.

FeatureSpecification objects may be populated and executed by Spring XML namespace element parsers on order to separate the concerns of XML parsing from Spring bean definition creation and registration. This type of use is mostly a framework-internal matter. More interesting to end users is the use of FeatureSpecification objects within @FeatureConfiguration classes and their @Feature methods. This functionality is new in Spring 3.1 and is the logical evolution of Spring's Java-based configuration support first released in Spring 3.0 (see @Configuration classes and @Bean methods). The primary goal of Feature-related support is to round out this Java-based support and allow users to configure all aspects of the Spring-container without requiring the use of XML. See "design notes" below for an example of this kind of use.

Notes on designing FeatureSpecification implementations

The public API of a FeatureSpecification should be designed for maximum ease of use within @Feature methods. Traditional JavaBean-style getters and setters should be dropped for a more fluent style that allows for method chaining. Consider the following example of a @Feature method:

 @Feature
 public TxAnnotationDriven tx(PlatformTransactionManager txManager) {
    return new TxAnnotationDriven(txManager).proxyTargetClass(true);
 }
 
Notice how the creation and configuration of the TxAnnotationDriven specification is concise and reads well. This is facilitated by mutator methods that always return the specification object's 'this' reference, allowing for method chaining. A secondary design goal of this approach is that the resulting code tends to mirror corresponding XML namespace declarations, which most Spring users are already familiar with. For example, compare the code above with its XML counterpart:

<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>

Typically, a user will call only the constructor and 'mutator' methods of a specification object. The accessor/getter methods, however, are typically called only by the specification's executor for the purpose of populating and registering bean definitions with the Spring container. For this reason, it is recommended that accessor methods be given package-private visibility. This creates a better experience for users from an IDE content-assist point of view as they will see only the public mutator methods, reducing any possible confusion.

Implementations should take care to allow for use of string-based bean names, placeholder ("${...}") and SpEL ("#{...}) expressions wherever they may be useful. While it is generally desirable to refer to dependent beans in pure Java, in certain cases a user may wish or need to refer to a bean by name. For example, the TxAnnotationDriven specification referenced above allows for specifying its transaction-manager reference by String or by PlatformTransactionManager reference. Such strings should always be candidates for placeholder replacement and SpEL evaluation for maximum configurability as well as parity with the feature set available in Spring XML. With regard to SpEL expressions, users should assume that only expressions evaluating to a bean name will be supported. While it is technically possible with SpEL to resolve a bean instance, specification executors will not support such use unless explicitly indicated.

See the Javadoc for @FeatureConfiguration classes and @Feature methods for information on their lifecycle and semantics.

Summary

Public Methods
abstract void execute(SpecificationContext specificationContext)
Execute this specification instance, carrying out the instructions specified within.
abstract boolean validate(ProblemReporter problemReporter)
Validate this specification instance to ensure all required properties have been set, including checks on mutually exclusive or mutually dependent properties.

Public Methods

public abstract void execute (SpecificationContext specificationContext)

Execute this specification instance, carrying out the instructions specified within. Should work by delegating to an underlying FeatureSpecificationExecutor for proper separation of concerns.

public abstract boolean validate (ProblemReporter problemReporter)

Validate this specification instance to ensure all required properties have been set, including checks on mutually exclusive or mutually dependent properties. May in some cases modify the state of the specification e.g., instantiating types specified as strings.

Returns
  • whether any problems occurred during validation
See Also
  • AbstractSpecificationExecutor#execute(Specification)