View Full Version : AOP and pattern design
moo
Oct 14th, 2004, 01:22 PM
Currently I'm doing some basic reading about the "extension object" pattern.
This pattern involves a lot of technical stuff like castings from A to B, asking for extensions....
Proposal: Instead of doing all this manually, it may be done through AOP. Now, the task is to translate this concern into an AOP aspect.
Problem: I have no pratical AOP experience.
Can someone help me to understand how this pattern may be translated to AOP.
Extension object:
A concrete base class, Subject, provides mechanisms to dynamically
add and query for extensions. A given extension must be
downcast to its specific interface (SpecificExtension) for use. The
pattern as a whole amounts to defining a standard way to cross
cast from one interface reference to another.
The aspect-oriented alternative to extension objects is extension
aspects (Figure eight). This approach eliminates the need for client
cross casting from one extension (or base interface) to another by
directly injecting the implementation of a specific interface into a
class seen by a given set of clients. Besides removing the cross
casting from client code, this approach reduces the run-time
overhead of the cross cast and the design complexity as measured
in number of classes and methods. The core functionality is more
reusable since its extension mechanism is not predefined via
inheritance from Subject and dependence upon Extension.
Excerpt taken from
http://www.cs.ubc.ca/~kdvolder/Workshops/OOPSLA2001/submissions/12-nordberg.pdf
Page 3/6
Thank you.
jbetancourt
Oct 14th, 2004, 03:17 PM
Though I'm not a Spring expert and have only begun to use AOP via Spring, it seems the "Extension Pattern" (after a very quick look) is used all over the place in Spring.
The reference manual has good stuff to get you started:
http://www.springframework.org/docs/reference/aop.html
BTW, here is another AOP Pattern reference: http://www.cs.ubc.ca/~jan/AODPs/
--- Josef Betancourt
moo
Oct 14th, 2004, 04:19 PM
String clazz = "com.moo.foo.bar"
AdapterA adaptA = SomeFactory.newInstance(AdapterA.class, clazz);
AdapterB adaptB = SomeFactory.newInstance(AdapterB.class, clazz);
Now consider the above code:
Suppose class "com.moo.foo.bar" implements two interfaces AdapterA and AdapterB and SomeFactory is a static Factory, trying to fullfill our expectations, which are:
1. SomeFactory has a build-in classloader that loads the specified class at runtime. (Assuming it to be in our classpath)
2. We want SomeFactory to create our Adapter objects without having to class cast manually.
3. The only information we want to pass, is the class name and the type of interface we expect.
4. SomeFactory should have only one newInstance method for any case, so we can add new interfaces easily, if our requirements have changed, without having to add a new newInstance for each type:
static Object newInstance(Class c, String clazz)
Can (Spring) AOP turn a generic return type like for instance "Object" into the demanded type at runtime?.
<dream>
The next enhancement could be:
String clazz = "com.moo.foo.bar"
AdapterA adaptA = SomeFactory.newInstance(clazz);
AdapterB adaptB = SomeFactory.newInstance(clazz);
Let AOP look at the demanded return type and it will cast dynamically from Object to AdapterA or AdapterB
</dream>
jbetancourt
Oct 14th, 2004, 05:33 PM
Would Spring's BeanFactory be able to fulfill bullet point three?
Object getBean(String,Class): returns a bean, registered under the given name. The bean returned will be cast to the given Class. If the bean could not be cast, corresponding exceptions will be thrown (BeanNotOfRequiredTypeException). Furthermore, all rules of the getBean(String) method apply (see above)
It seems that it could. But this is not really AOP just an example of a Factory pattern. But, I'll step aside and let the experts answer. :)
moo
Oct 14th, 2004, 07:16 PM
Would Spring's BeanFactory be able to fulfill bullet point three?
Object getBean(String,Class): returns a bean, registered under the given name. The bean returned will be cast to the given Class. If the bean could not be cast, corresponding exceptions will be thrown (BeanNotOfRequiredTypeException). Furthermore, all rules of the getBean(String) method apply (see above)
It seems that it could. But this is not really AOP just an example of a Factory pattern. But, I'll step aside and let the experts answer. :)
Thank you for posting the links, they are very helpfull!
It could, if your world remains static every single day 7/7 * 53 :)
Object getBean(String,Class): returns a bean, registered under the given name
but problem is the highlighted word "registered". So we are not talking about runtime conditions.
*And* we are completly circumventing Spring Factories, because SomeFactory uses a selfmade classloader.
oliverhutchison
Oct 14th, 2004, 10:03 PM
Why wrong with doing this?
AdapterA adaptA = (AdapterA) SomeFactory.newInstance(AdapterA.class, clazz);
As Java is strongly typed there's no way to avoid the cast.
moo
Oct 15th, 2004, 03:24 AM
Why wrong with doing this?
AdapterA adaptA = (AdapterA) SomeFactory.newInstance(AdapterA.class, clazz);
As Java is strongly typed there's no way to avoid the cast.
No I don't want to avoid casts. I do want to understand how AOP can help to build the "extension object" pattern and do the technical concerns for me. Maybe you are correct and this misuses AOP. But first I want to understand if it can be done, then I decide if I use it :)
katentim
Oct 15th, 2004, 08:50 AM
From figure 8:
An aspect-oriented extension to an existing class simply augments that class to directly or indirectly realize the desired specific interface, eliminating the run-time crosscasting mechanism of the Extension Object pattern.
You can introduce interfaces to classes (Ref. Manual Section 5.3.2.5. Introduction advice).
moo
Oct 17th, 2004, 11:30 AM
The DelegatingIntroductionInterceptor is designed to delegate an introduction to an actual implementation of the introduced interface(s), concealing the use of interception to do so. The delegate can be set to any object using a constructor argument; the default delegate (when the no-arg constructor is used) is this. Thus in the example below, the delegate is the LockMixin subclass of DelegatingIntroductionInterceptor. Given a delegate (by default itself) a DelegatingIntroductionInterceptor instance looks for all interfaces implemented by the delegate (other than IntroductionInterceptor), and will support introductions against any of them
Now this is quite difficult to understand!
Let's start with the first sentence
The DelegatingIntroductionInterceptor is designed to delegate an introduction to an actual implementation of the introduced interface(s), concealing the use of interception to do so.
Ok, the situation is, I'm loading a class via Class.forName() from whom I know that it implements one or more given interfaces.
You may describe it as
<T> object = <T> Class.forName("com.moo.bar")
where T is either InterfaceA, InterfaceB,...
So, at this moment I'm not interested in introducing an interface, because I already know what interfaces the loaded object implements. I'm only looking for a possibility to advice the above expression to dynamically replace parameter <T> depending on which interface is requested.
The next step could be to introduce new interfaces paired with new behaviour, to extend the object's capabilties. But I was glad, if could understand only the first part.
oliverhutchison
Oct 17th, 2004, 05:43 PM
<T> object = <T> Class.forName("com.moo.bar")
This makes no sence. The only types you can cast Class to are Class and Object. Do you mean?
<T> object = <T> Class.forName("com.moo.bar").newInstance()
So, at this moment I'm not interested in introducing an interface, because I already know what interfaces the loaded object implements. I'm only looking for a possibility to advice the above expression to dynamically replace parameter <T> depending on which interface is requested.
There is no way in Java to dynamically change a cast at runtime. Unless you use code generation or pure reflection you will *always* have to cast to the requied interface at some point. Can you please send through another explanation of what it is you are trying to do. I don't understand your examples so far.
Ollie
moo
Oct 18th, 2004, 01:12 PM
Do you mean?
<T> object = <T> Class.forName("com.moo.bar").newInstance()
You are correct . That's what I meant, sorry.
So, at this moment I'm not interested in introducing an interface, because I already know what interfaces the loaded object implements. I'm only looking for a possibility to advice the above expression to dynamically replace parameter <T> depending on which interface is requested.
There is no way in Java to dynamically change a cast at runtime. Unless you use code generation or pure reflection you will *always* have to cast to the requied interface at some point.
I know, that`s why I'm looking for an AOP solution.
Can you please send through another explanation of what it is you are trying to do. I don't understand your examples so far.
Ollie
Thanks! I will try to explain what I`m doing right now.
Before I have to apologize for my explanations if they get too verbose.
My english could be better, but I try my best.
Ok, I`m writing a small plug-in container.
The container
The plug-in container is a container with little functionality,
that might be expanded through a set of plug-ins.
So the main purpose of the container is to to manage the lifecycle
(start/stop/...) of the plug-ins and to do the nasty classloader
mechanics. All this will happen dynamically at runtime and I do this with
classworlds, a project at codehaus (http://classworlds.codehaus.org/)
Ok, that`s the container.
Now the plug-in.
Every plug-in consists of one JAR file and some sort of meta information
describing the plug-in`s functionality. This meta file is the
plug-in`s manifest. You might know this concept from the Eclipse project.
Now the plug-in's manifest describes how the plug-in relates to other
plug-ins within the container. This relationship is expressed by so called
"Extension Points" and "Extensions".
Assume you have a plug-in that adds an authorization service to
another plug-in that supports authentication.
To be able to add something you need an "extension point"
that accepts your extension (e.g. the authorization that want to add).
The authentication plug-in makes the extension point available to
the authorization plug-in that delivers the extension.
Back to the sceanrio:
At the time the container loads the authentication plug-in, this plug-in
might "ask" the engine to look for some other plug-in that has the
authorization functionality, i.e. extension. Now the combination of both
plug-ins might make up the login service, that will be controlled by
a third "login" plug-in.
Smallest common divisor
To assure a common point where all plug-ins can "meet",
all of these plug-ins must at least implement one interface
"IPlatformService" that includes two methods:
Class[] getExtensionPoints(); // returns all accepted services, i.e. interfaces
Class[] getExtensions(); // returns all supported services, i.e. interfaces
Now if the authentication plug-in "asks" the container to look out for an
authorization plug-in, then all plug-ins within reach of the container are
asked via call of "Class[] getExtensions();" whether they support the
requested extension for instance "com.moo.foo.auth".
The extension must implement this interface of the requesting caller
(i.e. its extension point). If they do so they are instanciated and
cast to the requested interface.
Because all this is done dynamically, the container cannot predict
what interface might be requested. It depends on the extension point of
the plugin. Therefore you cannot hard code the cast.
But the container can use the information retrieved by calls of
Class[] getExtensionPoints(); or Class[] getExtensions();.
Again, if getExtensionPoints() of some plug-in returns "com.moo.foo.auth"
the container asks all plug-ins by calling getExtensions() if they
support this interface. The container must than cast the loaded and
instanciated suitable object dynamically to the right interface.
Though only the information stated in the manifests of the plug-ins or
retrieved by getExtensions() must suffice, to accomplish this task.
The alternative
Of course, the container may pass objects as a mere "Object" to the
plug-in, delegating the responsability to cast the object to the plug-in
itself, but then the container looses the ability to control the whole
process and indeed the problem is moved out of the container but
not yet solved:
now every plug-in has to impement its own class casting logic.
I hope you now understand why I`m asking for this "autocasting"
feature.
<T> object = <T> Class.forName("com.moo.bar").newInstance()
Maybe I´m taking the wrong path and this "problem" is much easier to solve. I`ll will be glad to hear if there is a better solution.
oliverhutchison
Oct 18th, 2004, 05:42 PM
I don't think AOP is going to help you here.
The way I see it you've got two options:
1) define a single method on your plugin that accepts all extentions:
public void setExtention(Class extentionType, Object extention);
the problem with this is that your going to have to do casting and type checking in this method.
2) define a setter for each of the extentions that your plugin supports and use reflection to set the values:
public void setFooExtention(FooExtention foo);
public void setBarExtention(BarExtention bar);
this is a better solution as you don't have to worry about casting or type checking and easy to implement. All the type checking logic will have to be in your container. Have a look at BeanWrapperImpl for an easy way to get/set properties dynamically (this is what Spring uses in the bean factories).
Ollie
moo
Oct 19th, 2004, 01:17 PM
I don't think AOP is going to help you here.
The aspect-oriented alternative to extension objects is extension
aspects (Figure eight). This approach eliminates the need for client
cross casting from one extension (or base interface) to another by
directly injecting the implementation of a specific interface into a
class seen by a given set of clients. Besides removing the cross
casting from client code, this approach reduces the run-time
overhead of the cross cast and the design complexity as measured
in number of classes and methods. The core functionality is more
reusable since its extension mechanism is not predefined via
inheritance from Subject and dependence upon Extension.
Because of the quote I still hope AOP can help. Thanks for now, i see this problem is not of general interest. If I found a solution I will post it.
Mo
Powered by vBulletin® Version 4.2.1 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.