How does one implement multiton pattern using Spring Framework's facilities?
https://en.wikipedia.org/wiki/Multiton_pattern
I want to write a factory which takes a pair of client and supplier as arguments. The factory should always return a bean of type T. For a given pair of client and supplier, the instance of T return should be a singleton, but for a different pair of client and supplier, it will be a different instance of T. Please suggest a way to implement this without implementing boilerplate code that Spring may already provide.
Interface ClientSdk {
sendRequestToClient();
}
class ClientASdk implements ClientSdk {
}
class ClientBSdk implements ClientSdk {
}
enum Client {
ClientA,
ClientB;
}
enum Supplier {
SupplierA,
SupplierB;
}
class ClientSupplier {
private Client client;
private Supplier supplier;
}
class SdkFactory {
public ClientSdk getClientSdk(ClientSupplier clientSupplier) {
//For a given ClientSupplier, always return the same
//ClientSupplier instance
}
}
@Service
class ClientRequestService {
public sendRequestToClient(ClientSupplier clientSupplier) {
ClientSdk clientSdk = SdkFactory.getSdk(clientSupplier);
clientSdk.sendRequestToClient();
}
}
Here's a solution to your problem. It does make
SdkFactory
a bean as @crizzis suggests, but it also creates bean instances for eachClientSdk
instance so that each of them can be autowired or otherwise helped out by Spring. Note that I added anident()
method to theClientSdk
interface just to show that theMyClientSdk
beans have in fact been autowired with the SpringEnvironment
:Result:
Note that per the output, each of
client1
's andclient2
's ClientSdk objects are only created once, even though they're used multiple times. Also notice that since the call toident()
insendRequestToClient
prints the value of a property obtained by an autowiredEnvironment
instance, autowiring of eachClientSdk
object has worked.I do realize that I used a
String
instead of aClientSupplier
object as the identifying key for each ClientSdk object. I did that just to keep the example as simple as I could. I expect you can expand the example to replace theclientSupplier
String
with an instance ofClientSupplier
and somehow use that object as the key/identifier to insure that just oneClientSdk
instance is created perClientSupplier
. That detail isn't really germain to the basic idea here.Also, please note that the question itself changed while I was working on my implementation. Given that there are now exactly two subclasses of ClientSdk, you could simply make those regular
@Component
Spring beans. Having a small static number of those makes this problem less interesting. The technique I demonstrate here allows for an unlimited number of bean instances ofClientSdk
class without having to define a unique class for each of them. This requires that Spring create arbitrary instances of them based on runtime information. This was what the original form of the question seemed to be asking for.