In most use cases, most beans in a container are singletons. If a singleton bean needs to interact with another singleton bean, or a non-singler bean needs to interact with another non-singler bean, then typically the way to deal with a dependency is to define one bean as a property of the other. The problem arises if the life cycles of the beans are different. Suppose that a singleton bean A must use a non-singler bean (prototype) B, for example, every time a method is called in A. The container creates the singleton bean A only once, and thus the ability to set properties appears only once. The container cannot provide bean A with a new instance of bean B every time it is needed.

The solution is to give up some degree of inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface and calling getBean("B") on the container, requesting a (typically new) instance bean B whenever bean A needs it. The following example demonstrates this approach:

Java

// class that uses a stateful Command style class to perform some processing on
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    public Object process(Map commandState) {
        // create a new instance of the corresponding
        Command Command command = createCommand();
        // set the state for the (expectedly brand new)
        Command instance command.setState(commandState);
        return command.execute();
    }
    protected Command createCommand() {
         // note the Spring API dependency!
         return this.applicationContext.getBean("command", Command.class);
    }
    public void setApplicationContext(
         ApplicationContext applicationContext) throws BeansException {
         this.applicationContext = applicationContext;
        }
}
Kotlin

// class that uses a stateful Command style class to perform specific processing
package fiona.apple
// Spring-API imports
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware
class CommandManager : ApplicationContextAware {
    private lateinit var applicationContext: ApplicationContext
    fun process(commandState: Map<*, *>): Any {
        // create a new instance of the corresponding Command
        val command = createCommand()
        // set the state for the (expectedly brand new)
        Command instance command.state = commandState
        return command.execute()
    }
    // note the dependency on the Spring API !
    protected fun createCommand() =
            applicationContext.getBean("command", Command::class.java)
    override fun setApplicationContext(applicationContext: ApplicationContext) {
        this.applicationContext = applicationContext
    }
}

The previous option is not desirable because the business code (domain layer) is aware of and bound to the Spring framework. Method Injection is a slightly advanced Spring IoC container feature that allows you to handle this use case cleanly.

You can read more about the advisability of dependency injection through a method in this blog entry.

Dependency injection via lookup

Dependency injection via lookup is the ability of a container to override the methods of container-managed beans and return the search result for another named bean in the container. The search typically involves a prototype bean, as in the scenario described in the previous section. The Spring framework implements this dependency injection through a method, using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method.

  • For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the overridden method cannot be final either.

  • Unit testing a class that has an abstract method requires you to subclass the class yourself and provide an implementation of the stub function abstract method.

  • Concrete methods are also needed to scan components, which require specific classes.

  • Another key limitation is that lookup methods do not work with factory methods and in particular with @Bean methods in configuration classes, since in this case the container is not responsible for instantiation and therefore does not can create a runtime-generated subclass on the fly.

In the case of the CommandManager class in the previous code snippet, the Spring container dynamically overrides the method implementation createCommand(). The CommandManager class does not have any Spring dependencies, as the reworked example shows:

Java

package fiona.apple;
// no more Spring imports!
public abstract class CommandManager {
    public Object process(Object commandState) {
       // create a new instance of the corresponding interface
       Command Command command = createCommand();
       // set the state for the (expectedly brand new)
       Command instance command.setState(commandState);
       return command.execute();
       }
       // ok... but where is the implementation of this method?
       protected abstract Command createCommand();
}
Kotlin

package fiona.apple
// no more Spring imports!
abstract class CommandManager {
    fun process(commandState: Any): Any {
        // create a new instance of the appropriate Command interface
        val command = createCommand()
        // set the state for the (expectedly brand new) Command instance
        command.state = commandState
        return command. execute()
    }
    // ok... but where is the implementation of this method?
    protected abstract fun createCommand(): Command
}

In the client class containing the method to be injected (in this case CommandManager), must have a signature like this:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

If a method is an abstract, then the dynamically generated subclass implements that method. Otherwise, the dynamically generated subclass overrides the concrete method defined in the original class. Consider the following example:


< !-- a stateful bean deployed as a prototype (not a singleton) -->
<bean id="myCommand" class="fiona.apple.AsyncCommand" scope="prototype">
    <!-- inject dependencies here as needed -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
    <lookup-method name="createCommand" bean="myCommand"/>
</bean>

The bean identified as commandManager calls its own createCommand() whenever it needs a new instance of the myCommand bean. Deploying the myCommand bean as a prototype should be done with caution unless absolutely necessary. If it is a singleton bean, then the same instance of the myCommand bean will be returned each time.

Alternatively, in an annotation-based component model, you can declare a lookup method using the annotation @Lookup, as shown in the following example:

Java

public abstract class CommandManager {
    public Object process(Object commandState) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }
    @Lookup("myCommand")
    protected abstract Command createCommand();
}
Kotlin

abstract class CommandManager {
    fun process(commandState: Any): Any {
        val command = createCommand()
        command.state = commandState
        return command.execute()
    }
    @Lookup("myCommand")
    protected abstract fun createCommand(): Command
}

Or more typically, you can rely on the target bean to be resolved according to the declared return type of the lookup method:

Java

public abstract class CommandManager {
    public Object process(Object commandState) {
        Command command = createCommand();
        command.setState(commandState);
        return command.execute();
    }
    @Lookup
    protected abstract Command createCommand();
}
Kotlin

abstract class CommandManager {
    fun process(commandState: Any): Any {
        val command = createCommand()
        command.state = commandState
        return command.execute()
    }
    @Lookup
    protected abstract fun createCommand(): Command
}

Note that how Typically, such annotated lookup methods should be declared with a specific stub function implementation so that they are compatible with Spring bean scanning rules, where abstract classes are ignored by default. This restriction does not apply to explicitly registered or explicitly imported bean classes.

Another way to access target beans that are in different scopes is the dot implementation of ObjectFactory / Provider. See " Beans in scope as dependencies".

You may also find the ServiceLocatorFactoryBean (in the org.springframework.beans.factory.config package) useful.

Custom method replacement

A less useful form of method dependency injection than lookup method dependency injection is the ability to arbitrarily replace methods in a managed bean with another method implementation. You can safely skip the rest of this section until you need this functionality.

With XML-based configuration metadata, you can use the replaced-method element to replace an existing method implementation with another for the expanded bean. Consider the following class, which has a computeValue method that we need to override:

Java

public class MyValueCalculator {
    public String computeValue(String input) {
        // some real code...
    }
    // some other methods...
}
Kotlin

class MyValueCalculator {
    fun computeValue(input: String): String {
        // some real code...
    }
    // some other methods...
}

A class that implements the interface org.springframework.beans.factory.support.MethodReplacer provides a new method definition, as shown in the following example:

Java

/**
 * is intended to override an existing computeValue(String).
 * implementation in MyValueCalculator
 */
public class ReplacementComputeValue implements MethodReplacer {
    public Object reimplement(Object o, Method m, Object[] args) throws Throwable {
        // get the input value, work with it and return the calculated result
        String input = (String) args [0];
        ...
        return ...;
    }
}
Kotlin

/**
 * is intended to override an existing computeValue(String).
 * implementation in MyValueCalculator
 */
 class ReplacementComputeValue : MethodReplacer {
    override fun reimplement(obj: Any, method: Method, args: Array<out Any>): Any {
        // get the input value, work with it and return the calculated result
        val input = args[0] as String;
        ...
        return ...;
    }
}

The definition of a bean to expand the original class and set the override method will look like this:


<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">
    <!-- arbitrary method replacement -->
    <replaced-method name="computeValue" replacer="replacementComputeValue">
        <arg-type>String</arg-type>
    </replaced-method>
</bean>
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>

You can use one or more <arg-type/> elements inside a <replaced-method/> element to specify the method signature of the method being overridden. A signature for arguments is only needed if the method is overloaded and there are multiple variants in the class. For convenience, the type string for the argument can be a substring of the fully qualified type name. For example, all of the following correspond to java.lang.String:


java.lang.String
String
Str

Since the number of arguments is often sufficient to distinguish between each possible option, this shortcut can save a lot of time by allowing you to enter only the shortest string that matches the argument type.