|
|||||
|
|||||
Type Based Post Instantiation
ProblemIn Post Instantiation with AspectJ, we presented a solution that uses an "Injection" interface to encapsulate the injection logic described in the xml file. This enables the domain object to be pojo without any dependency to the container. Yet, there is an awkward problem: we need an aspect defined for each different domain object type. This is necesssary for us to appy different injection logic based on the domain object type. Though the aspect is trivial, it is still painful to write them down for our one thousand and fourty seven domain object types. In Annotation Based Auto Wiring, we gave a solution that uses autowiring and annotation to eliminate the need for such trivial aspects. Nice as it is, it is however possible that autowiring doesn't work, or annotation can't be used. In this article, we'll give a more comprehensive solution that address the problem completely. SolutionWe will only need to write one (or, a few more maybe) aspect: import jfun.yan.etc.injection.Injection; public abstract aspect BaseInjectionAspect { private Injection injection; public void setInjection(Injection inj){ this.injection = inj; } /** * the creation of any object that is a client of the * Person.new service */ abstract pointcut clientCreation(Object aClient); /** * inject clients when they are created */ after(Object aClient) returning : clientCreation(aClient) { injection.inject(aClient); } } public aspect DomainInjectionAspect extends BaseInjectionAspect{ /** * the creation of any object that is a client of the * Person.new service */ pointcut clientCreation(Object aClient) : initialization(com.mycompany.domainmodels.*+.new(..)) && this(aClient); } Now, suppose we have several domain object types: Person, Fruit, Apple and Orange, where Apple and Orange are subclasses of Fruit. Our configuration file will be look like: <module name="test aspectj"> <nut name="injector" class="jfun.yan.xml.nuts.optional.InjectorAspectNut"/> <!-- load the typecase tag --> <nut name="typecase" class="jfun.yan.xml.nuts.optional.InjectionTypeCaseNut"/> <body> <bean id="service1" .../> <bean id="service2" .../> <!-- ALL SORTS OF INJECTION LOGIC START HERE --> <function id="inject person" params="person"> <bean component="$person" props="{service1=$service1}"/> </function> <function id="inject fruit" params="fruit"> <bean component="$fruit"> <prop key="name"> <getter component="$fruit" name="class.name"/> </prop> <prop key="service1" val="$service1"/> </bean> </function> <function id="inject orange" params="orange"> <bean component="$orange" props="{name=orange,service1=$service1,service2=$service2}"/> </function> <!-- ALL SORTS OF INJECTION LOGIC END HERE --> <!-- use typecase to glue them together --> <typecase id="the_injection"> <case type="com.mycompany.domainmodels.Orange" injection="$inject orange"/> <case type="com.mycompany.domainmodels.Fruit" injection="$inject fruit"/> <case type="com.mycompany.domainmodels.Person" injection="$inject person"/> </typecase> <!-- use the type-case'd injection to configure the generic aspect --> <injector class="com.mycompany.DomainInjectionAspect" injection="$the_injection"/> </body> </module>
In this configuration file, we use "inject orange", "inject fruit", "inject person" to describe different injection logic for different types. We then use the <typecase> tag implemented by InjectionTypeCaseNut class to add the "typecase" logic to the final Injection object. Finally, the <injector> tag is used to configure the DomainInjectionAspect. |
|||||
|
Copyright 2003-2006 - The Codehaus. All rights reserved unless otherwise noted.
Powered by Atlassian Confluence
|
|||||