Hey, I'm just making sure this is an appropriate place to ask before I
take the time to lay out my problem. This seems like a reasonable place
to ask but the rest of the group may not agree....
Obviously. I haven't asked a specific question yet. I wanted to be sure
there was no major objection before laying out the issue.
There are dozens of things I'd like to learn about Java and I probably
need to learn several of them first.
Based on other answers to my question, maybe I _don't_ want to learn
AspectJ!
I saw a seminar about aspects a couple of years back and thought it
sounded quite intriguing. It struck me that aspects might be a very good
way to handle what I am currently trying to do. But maybe there are
better ways. So let me lay out what I'm trying to accomplish and maybe
you can suggest a better approach.
I'd like to make both localization and logging a part of every class that
I write. The localization would allow each class to display text in any
(supported) language that the user requests and I'm also thinking of
localizing the messages in exceptions that get displayed or written to
logs. It seems like logging is the standard way to go for writing and/or
displaying messages to the user and to logs.
Now, I could go and add very similar code to lots and lots of classes to
accomplish those things but maybe writing aspects would enable me to
write a few lines of code that apply to EVERY class I've written. One
aspect could verify that a Locale had been passed to the class (assuming
it is invoked from another class) or throw an exception if it hadn't.
Another aspect could do something similar for the logger.
This is still just half-baked in my head but maybe it's clear enough that
you get the gist of it.
I'd be interested in the advice of the group on this issue.
By the way, I found another place to ask AspectJ questions and the issues
I had when I first posted here are now resolved. But the bigger issue
remains: are aspects a good approach for what I want to do? If not, what
would be a better strategy?
A bit of reasoning can go a long ways to telling you whether aspects
make sense for a particular job. This reasoning starts with an
examination of the join points that AspectJ makes available in its join
point model (JPM). You'll find this information tabulated in the AspectJ
programming guide.
You'll see that the join points available to us in AspectJ include
method calls/executions. The method call/execution join points have
state, one piece of which is the object array of method arguments. As
you might expect the other pieces of state are the objects involved
(only one for the method execution join point).
You also know, or should be starting to understand, that pointcuts are
the mechanism by which you choose *which* join points are in use. This
can be very powerful: for the method execution join point you could
easily select only the public methods for a given class, and that
becomes a certain pointcut that you use.
Dynamic pointcuts would even allow you to say that, for example, if you
have defined a pointcut, say Pointcut 1, that selects all the public
methods for class A (more precisely, selects the join points that
represent the executions for all the public methods in class A), that
you are also interested in the executions of methods that happen within
the context of those join points. In other words, if "public
A.someMethod(args)" runs, that's been identified by Pointcut 1. Pointcut
2 could include any methods that are *called by* A.someMethod(args).
Finally, with the _advice_, you have even more control on what code you
run at each selected join point, *when* you run it in temporal relation
to the join point (e.g. maybe you run some code if the method threw an
exception), and even whether you run the code at all. And as you might
expect, the advice knows about certain state - advice associated with a
pointcut has access to the state of the join points. So an advice
associated with our Pointcut 1 sees the method arguments.
Of all the other join points available in AspectJ, let's keep field
assignment and constructor calls/executions in mind as well, as we think
logging.
So let's consider logging, armed with all of this knowledge. If nothing
else, you know that you can log method calls & executions with great
flexibility. If you wanted to, you could be logging, using log4j say,
messages out at an error or warn level for exceptions thrown by any
methods which are called by public methods in package org.whatsit.*. At
the same time you might log the public calls in that package at debug level.
As an aside, you can see why this type of application of AOP is called
tracing. Very powerful tracing, but still execution tracing.
But, and this is one main "but", you don't have access to the guts of
interesting methods unless the internals are also identifiable by join
points. If there is an important conditional, the correct behaviour of
which is bedevilling you, and which relies on local variables computed
in a local chunk of code in that method, AspectJ has no eyes on it.
You're not going to be logging this kind of thing with aspects.
Another big "but", maybe not so much a "but" rather a general
consideration, is that if you start getting very fine-grained about
pointcuts, you're sort of defeating the purpose of AOP. We're, I expect,
considering a codebase that has no extensive logging, maybe none. If you
are going to spend inordinate amounts of time tailoring pointcuts and
advice for umpteen different types of logging, *you may as well bite the
bullet and go into the code and directly use the logging framework*,
rather than apply it through the agency of aspects.
In a nutshell, for logging, I myself have used AspectJ for emergency
maintenance: the codebase in question has no logging, or what it has is
useless, and there is limited time to add logging to source. So this is
execution tracing logging.
I hope this helps.
AHS