Date: 2004-03-04T23:59:37
Editor: 130.89.169.128 <>
Wiki: JicarillaWiki
Page: http://lsd.student.utwente.nl/jicarilla/IocContainerInternals_2fTheBasics_2fTheSmartHashMap
no comment
New Page:
[wiki:IocContainerInternals Contents] | [wiki:IocContainerInternals/TheBasics/TheGlorifiedHashMap Previous] | [wiki:IocContainerInternals/TheBasics/TheComponentizedContainer Next]
= The Smart HashMap =
''(part of the IocContainerInternals paper)''
== What just happened? ==
Okay, so we got a taste of how to decorate the basic {{{Map}}} interface to do some useful IoC-container-style stuff for us on the [wiki:IocContainerInternals/TheBasics/TheGlorifiedHashMap previous page]. By introducing a support class to our rather trivial example, we were able to remove some concerns from our main piece of code. We moved the following responsibilities to the container:
1. Holding our components. Both their definitions (where a definition for us was a class plus an associated name), and their instances (of which we only directly retrieved the {{{JFrame}}}, we didn't even care about the button instances).
1. Creating our components. We removed all our "{{{new XXXThingie()}}}" statements, remember?
1. Wiring our components together. We made the container responsible for adding the buttons to the frame.
== The fundamental concerns ==
What we've done, in fact, is seperate out concerns. Let us identify a few of the concerns present in our trivial example:
1. interacting with the JVM and the command line (fancy term: container embedding)
1. declaring the components to use (fancy term: assembly)
1. creating components (fancy term: creating components)
1. managing components (fancy term: can't think of any right now)
1. wiring components together (fancy term: dependency resolution)
1. application logic (fancy term: domain modelling decomposition and modelling)
the funny thing is ("Stop looking at that squirrel!"), each and every one of these concerns is present in each and every java application. Items 1,3,4 and 5 seem like good candidates for writing once, then re-using everywhere. Item 2 is of course specific to an application (what a componentized application does is determined by what components you pick and how they interact). With item 6...well, some components (which embody our application logic) will be re-used across many projects (like the {{{JButton}}} we used), and some will be application-specific.
== The challenge ==
Build something that can handle item 1,3,4 and 5 for each and every software application.
== Meeting that challenge ==
We know how to do this for some things. Others are more difficult. We'll start simple.
=== Creating Components ===
For example, we know that if we want to isolate component creation from the component itself, what we use is a {{{Factory}}}. Factories are used all over the place. Something like this
{{{
class JButtonFactory
{
JButton getInstance()
{
return new JButton();
}
JButton getInstance( String caption )
{
return new JButton( caption );
}
}
}}}
may not seem very powerful (the getInstance() method just wraps a constructor), but if you make things a little more generic, you can do all kinds of things. I won't talk about this very much here (its called the factory pattern if you need to google it up), but lets just go for a real simple and generic factory in our examples:
{{{
public interface Factory
{
Object getInstance();
}
}}}
=== Interacting with the JVM ===
I lied a moment ago. I said we wanted to solve this one once for each and every application. The truth is we want to solve it several times. We want to do this for commandline programs with a {{{main()}}} method, but we also want to do it for web applications (deployed inside a servlet engine), enterprise applications (deployed inside a J2EE server), applets (deployed inside a browser), and other applications.
Okay, so let's recognize that we need several environments in which to embed the container. The container needs high embeddability. Let's leave it at that for now.
=== Wiring components together ===
This is the really interesting part! Martin Fowler wrote [http://www.martinfowler.com/articles/injection.html a nice piece] about IoC component wiring recently, so I can be brief. If I have the simpson family, I might manually wire them together like this:
{{{
public Marge marge = new MargeImpl();
public Homer homer = new HomerImpl( marge );
public Bart bart = new BartImpl( homer, marge );
public Lisa lisa = new LisaImpl( homer, marge );
public Maggie maggie = new MaggieImpl( homer, marge );
}}}
one of the big things IoC containers do for you is taking this work out of your hands. Consider this bit of pseudocode:
{{{
function assemble()
{
add( Bart )
add( Homer )
add( Lisa )
add( Maggie )
add( Marge )
}
function wire() { perform-equivalent-of-previous-sample-here() }
assemble()
wire()
getMarge().frown()
}}}
this kind of "delegated wiring" might not seem like a huge advantage above doing the wiring manually as in the first example, but once you have dozens of components with much more complex interdependencies, changing interdependencies, and many places where you call the constructors, it really is. This is such a '''big timesaver'''. And it is quite possible. I'm not going to show you all the code needed to do the above (it requires some smart reflection magic), but here's a (simplified from actual code) snippet:
{{{
public Object[] getDependenciesFor( Class clazz )
{
Constructor[] constructors = clazz.getConstructors();
Constructor constructor = findTheRightConstructor( constructors );
Class[] parameterTypes = constructor.getParameterTypes();
Object[] parameterValues = new Object[parameterTypes.length];
for( int i = 0; i < parameterTypes.length; i++ )
{
Class parameterType = parameterTypes[i];
Object parameterValue = getParameterValue( parameterType );
parameterValues[i] = parameterValue;
}
return parameterValues;
}
}}}
Hopefully you can imagine how reflection utilities like this can be used inside a container. Something like
{{{
public void add( Object key, Class clazz )
{
m_classes.put( key, clazz )
Object constructorArgs = getDependenciesFor( clazz );
Object instance = getInstance( clazz, constructorArgs );
m_instances.put( key, instance );
}
public Object get( Object key )
{
return m_instances.get( key );
}
}}}
=== Managing components ===
This may sound like a big term, but the little bit of sample code above already does component management: it keeps track of the component declaration ({{{m_classes.put( key, args )}}}, and also of the instances of those components {{{m_instances.put( key, args )}}}. Full-featured containers may have options for allowing multiple instances of a declaration, for associating an instance of a declaration with each client, for removing components, etc etc.
== Contracts ==
Okay, so it seems possible to really provide a usable generic way to handle at least some of these responsibilities. Sweet! But in order for all this to work, we really do need to be real clear about some contracts
* that between the container embeddor and the container
* that between the container assembler and the container
* that between the container and the components
----
Okay, this page is getting long, and I'm really getting carried away with talk about contracts, definitions, responsibilities, and fancy terms for all kinds of different things. You've had enough of a taste of all this I guess. I think I need another beer. See you on the next page.
----
[wiki:IocContainerInternals Contents] | [wiki:IocContainerInternals/TheBasics/TheGlorifiedHashMap Previous] | [wiki:IocContainerInternals/TheBasics/TheComponentizedContainer Next]
-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.