The Spring container instantiates and configures beans defined in the context of your application. You can also ask the bean factory to configure an already existing object by specifying the name of the bean definition that contains the configuration that you want to apply. spring-aspects.jar contains an annotation-driven aspect that uses this capability to perform dependency injection on any object. Support is intended for objects created outside the control of any container. Domain objects often fall into this category because they are often created programmatically using the new operator or using an object-relational mapping (ORM) tool as a result of a database query.

The @Configurable annotation marks the class as suitable for Spring-based configuration. In the simplest case, you can use it as a purely marker annotation, as shown in the following example:

Java

package com.xyz.myapp.domain;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable
public class Account {
    // ...
}
Kotlin

package com.xyz.myapp.domain
import org.springframework.beans.factory.annotation.Configurable
@Configurable
class Account {
    // ...
}

When used this way as a token interface Spring configures new instances of an annotated type (in this case Account) with a bean definition (usually scoped at the prototype level) with the same name as the fully qualified type name(com.xyz.myapp.domain.Account). Because the default name for a bean is the fully qualified name of its type, a convenient way to declare a prototype definition is to omit the id attribute, as shown in the following example:


<bean class="com.xyz.myapp.domain.Account" scope="prototype">
    <property name="fundsTransferService" ref="fundsTransferService"/>
</bean>

If you need to explicitly specify the name of a prototype bean definition for later use, you can do so directly in the annotation, as shown in the following example:

Java

package com.xyz.myapp.domain;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable("account")
public class Account {
    // ...
}
Kotlin

package com.xyz.myapp.domain
import org.springframework.beans.factory.annotation.Configurable
@Configurable("account")
class Account {
    // ...
}

Spring will now look for a bean definition named account and use that as the definition for configuring new instances of Account.

You can also use automatic detection and linking to avoid specifying a dedicated bean definition at all. To have Spring apply automatic discovery and wiring, use the autowire property of the @Configurable annotation. You can specify either @Configurable(autowire=Autowire.BY_TYPE) or @Configurable(autowire=Autowire.BY_NAME) to automatically detect and associate by type or by name, respectively. As an alternative, it is preferable to specify explicit, annotation-based dependency injection for your @Configurable annotated beans via the @Autowired or @Inject annotations at the field level or method.

Finally, you can enable Spring dependency checking for object references in a newly created and configured object using the dependencyCheck attribute (for example, @Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)). If this attribute is set to true, then after configuration is complete, Spring will check that all properties (that are not primitives or collections) have been set.

Note that using the annotation itself is gives nothing to himself. It is the AnnotationBeanConfigurerAspect in spring-aspects.jar that acts when an annotation is present. Essentially, the aspect says: "Upon returning from initializing a new object of type annotated with @Configurable, configure the newly created object using Spring according to the properties of the annotation." In this context, "initialization" refers to newly created instances of objects (for example, objects instantiated using the new operator), as well as Serializable objects that are deserialized (for example, via readResolve()).

One of the key phrases in the above paragraph is "as a matter of fact." In most cases, the exact semantics of "on return from initializing a new object" will be appropriate. In this context, "after initialization" means that dependencies are injected after the object is constructed. This means that dependencies are not available for use in class constructor bodies. If you need to inject dependencies before the constructor bodies begin executing, and thus make them available for use in the constructor body, you need to define this in the @Configurable annotation declaration as follows:

Java
@Configurable(preConstruction = true)
Kotlin
@Configurable(preConstruction = true)

For more information on the language semantics of the various slice types in AspectJ, you can find in this appendix to AspectJ Programming Guide.

For this to work, the annotated types must be bound using AspectJ binding tool. To do this, you can use either an Ant or Maven task at build time (see for example AspectJ Development Environment Guide), or linking at load time. The AnnotationBeanConfigurerAspect itself must be configured by Spring (to obtain a reference to the bean factory that will be used to configure new objects). If you are using Java based configuration, then you can add @EnableSpringConfigured to any @Configuration class as shown below:

Java

@Configuration
@EnableSpringConfigured
public class AppConfig {
}
Kotlin

@Configuration
@EnableSpringConfigured
class AppConfig {
}

If you prefer XML-based configuration, the context namespace in Spring defines a convenience element context:spring-configured, which can be used like this:

<context:spring-configured/>

If object instances marked with the @Configurable annotation are created before the aspect has been configured, which results in a message appearing in the debug log and the object configuration fails. An example would be a bean in a Spring configuration that creates domain objects when it is initialized by Spring. In this case, you can use the bean's depends-on attribute to manually indicate that the bean depends on a configuration aspect. The following example shows how to use the depends-on attribute:


<bean id="myService"
        class="com.xzy.myapp.service.MyService"
        depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">
    <!-- ... -->
</bean>
Do not enable @Configurable handling via aspect of the bean's configurator, unless you need to use its semantics at runtime. In particular, make sure that you do not use the @Configurable annotation on bean classes that are registered in the container as regular Spring beans. This will result in double initialization - once through the container and once through the aspect.

Unit testing objects annotated with @Configurable

One of the purposes of supporting the @Configurable annotation is the ability to independently unit test domain objects without the hassle of hard-coded sequential lookups. If types marked with the @Configurable annotation have not been bound by AspectJ, then the annotation will have no effect on unit testing. You can set property references to a mock object or stub function in the object under test and continue working as normal. If types with the @Configurable annotation have been bound by AspectJ, you will still be able to unit test outside the container as normal, but whenever you construct an object with the @Configurable annotation you will see warning message indicating that it has not been configured by Spring.

Working with multiple application contexts

AnnotationBeanConfigurerAspect, which is used to implement support @Configurable, is a single instance of an AspectJ aspect. The scope of a single instance of an aspect is the same as the scope of static members: For each class loader, there is one type-defining aspect instance. This means that if you are defining multiple application contexts within the same class loader hierarchy, you need to think about where to define the bean annotated with @EnableSpringConfigured and where to place spring-aspects.jar on the classpath.

Consider a typical Spring web application configuration, which has a common parent application context defining common business services, everything needed to support those services, and one child application context for each servlet ( which contains definitions specific to this servlet). All of these contexts coexist in the same class loader hierarchy, and therefore AnnotationBeanConfigurerAspect can only contain a reference to one of them. In this case, it is recommended to define the @EnableSpringConfigured bean in the general (parent) application context. This identifies the services that you might want to inject into your domain objects. The consequence of this is that you will not be able to configure domain objects with references to beans defined in child (servlet-specific) contexts using the @Configurable annotation mechanism (which you probably wouldn't want anyway).

When deploying multiple web applications in the same container, ensure that each web application loads types from spring-aspects.jar using its own class loader (for example, by placing spring-aspects.jar in WEB-INF/lib). If spring-aspects.jar is only added to the general container-wide classpath (and therefore loaded a common parent class loader), all web applications will use the same aspect instance (which you probably don't want).