LookupAndSpring
From APIDesign
(→Double Injection) |
(→Double Injection) |
||
Line 29: | Line 29: | ||
and it composition together becomes piece of cake. Instead of writing complicated binding [[XML]] file or doing inefficient on start scan of all resources in a package, one can just put all three [[JAR]] files into classpath and they look each other up effectively and unrestrainably. | and it composition together becomes piece of cake. Instead of writing complicated binding [[XML]] file or doing inefficient on start scan of all resources in a package, one can just put all three [[JAR]] files into classpath and they look each other up effectively and unrestrainably. | ||
- | In some sense this represent an example of double [[injection]]. First of all we instructed the [[Spring]] framework to do its [[ | + | In some sense this represent an example of double [[injection]]. First of all we instructed the [[Spring]] framework to do its [[Dependency Injection]] to provide necessary implementations to the ''Anagrams'' class constructor. Yet, these implementations are unknown at compile time of the [[JAR]] and they are not present in any single configuration file. Instead they are picked up from the runtime classpath by using ''Java Extension Mechanism'' as abstracted by [[Lookup]]''.getDefault()''. |
I am not sure if this kind of ''double'' [[injection]] can be useful in web applications where developer is also kind of assembler putting everything together, but in [[Use Modular Architecture|modular applications]] it has its place. If you are interested, see and use the [[Spring]]/[[Lookup]] bridge: | I am not sure if this kind of ''double'' [[injection]] can be useful in web applications where developer is also kind of assembler putting everything together, but in [[Use Modular Architecture|modular applications]] it has its place. If you are interested, see and use the [[Spring]]/[[Lookup]] bridge: |
Revision as of 20:01, 27 April 2009
An important subset of Spring is said to be an example of Dependency Injection. Lookup library, originally invented by NetBeans project used to be said to do similar kind of injection. Well, both are different, yet similar. Both are optimized for slightly different tasks, could they strengthen themselves if they worked together? That it what we'll find out soon.
Imagine there is a GUI application to play the Anagrams Game. We have a base UI class called Anagrams that needs two additional interfaces to be injected. In Spring world, this can be done with a two arguments constructor:
Code from Anagrams.java:
See the whole file.public class Anagrams extends javax.swing.JFrame implements UI { private WordLibrary wordLibrary; private Scrambler scrambler; public Anagrams(WordLibrary w, Scrambler s) { wordLibrary = w; scrambler = s; init(); } }
and an XML configuration file:
Code from Main.xml:
See the whole file.<bean
id="ui"
class="org.apidesign.demo.anagramwithspringandlookup.Anagrams"
autowire="autodetect"
/>
If used in classical Spring sense, the configuration file would have to refer to implementations of both constructor arguments, in order to let the Anagrams class to be properly wired. While this is fine in close world of web applications, when one knows all the libraries running on the server, this may be too restricted in world of modular applications that are assembled together by someone else than the developer of the Anagrams implementation.
To open door to others to inject various implementations of WordLibrary and Scrambler classes and can use Java Extension Mechanism as abstracted by Lookup. Just compose your own XML context with the Java Extension one in your main method:
Code from Main.java:
See the whole file.public static void main(String[] args) throws Exception { ApplicationContext servicesContext = SpringAndLookup.create( Lookup.getDefault(), "java.extensions" ); ClassPathXmlApplicationContext mergedContext; mergedContext = new ClassPathXmlApplicationContext( new String[] { "Main.xml" }, Main.class, servicesContext ); UI ui = (UI)mergedContext.getBean("ui", UI.class); ui.display(); }
This creates an unfinished, open application to be extended by other JARs composed together by its assembles, yet the application JavaBeans can user the classical Spring Dependency Injection style of developement (just like the Anagrams class shows.
Double Injection
Yet, if there are extensions written according to the Java Extension mechanism or using the @ServiceProvider annotation offered by the Lookup library, one can have two JAR files with:
Code from SimpleScrambler.java:
See the whole file.@ServiceProvider(service=Scrambler.class) public class SimpleScrambler implements Scrambler { private static final Random random = new Random(); public String scramble(String word) { } }
and another one with:
Code from StaticWordLibrary.java:
See the whole file.@ServiceProvider(service=WordLibrary.class) public class StaticWordLibrary implements WordLibrary { }
and it composition together becomes piece of cake. Instead of writing complicated binding XML file or doing inefficient on start scan of all resources in a package, one can just put all three JAR files into classpath and they look each other up effectively and unrestrainably.
In some sense this represent an example of double injection. First of all we instructed the Spring framework to do its Dependency Injection to provide necessary implementations to the Anagrams class constructor. Yet, these implementations are unknown at compile time of the JAR and they are not present in any single configuration file. Instead they are picked up from the runtime classpath by using Java Extension Mechanism as abstracted by Lookup.getDefault().
I am not sure if this kind of double injection can be useful in web applications where developer is also kind of assembler putting everything together, but in modular applications it has its place. If you are interested, see and use the Spring/Lookup bridge:
Leave here comments about your satisfaction, disappointment and my confusion.
<comments/>