I thought this was a great analogy. One of my favorite teaching techniques is to introduce a new concept as a variation of something you know, vs. presenting it in an vacuum.
Agreed. Analogies can open the doors in someone's mind. The hard part, though, is coming up with the analogy. If your goal is to teach something, it's hard to come up with one that people can relate to.
Java has some add-on libraries that do it. It's hard to judge whether it's a good idea there because Java's OO is so brain-dead by design that it's hard to tell whether a technique is truly good, or just offsetting Java's utter simplicity. (By "by design", I mean that Java chose its simple model; it is by design. It is so simple that it is very difficult to use any sort of sophisticated programming technique without serious external libraries or immense class hierarchies.)
Many other languages have things that are very similar, certainly more "aspect oriented" than CSS. Lisp can do this very easily, and emacs uses something very like it a lot, complete with similar terminology for "advice". Ruby and Javascript's monkeypatching can be seen as something very like aspect oriented programming. Writing your own aspect system is pretty easy; I've got something in work in Perl that actually has things called aspects, for instance.
In each case, pedants will justifiably point out that they aren't actually "aspect-oriented" according to some strict definition, but I've sworn off caring about whether something meets a strict definition unless you can show me at least one scientific study of reasonable scope that verifies that things meeting a particular definition are good and even small deviations from the particular definition show noticeably worse performance. (See also: arguing about exactly what the "unit" in "unit" test means as if it actually has any actual force behind it.) I will say that each of them shares enough similarities that it crowds out the full technical definition of "aspect oriented". It's not a coincidence that the term became large in Javaland. See also "dependency injection", where what was common practice in other languages actually grew a pattern name in Java because it's so much harder you have to do it deliberately, instead of accidentally like you can in better languages.
(Yeah, I will cop to thinking Java is a very technically weak language, in the sense it takes reams of code to do anything useful from a design standpoint. That doesn't mean it's bad, but it does mean I personally don't like it and I do not apologize for my personal preferences.)
AspectJ (http://www.eclipse.org/aspectj/) is IMO a pretty good implementation. I've used it recently for an Android application. Gregor Kiczales (http://www.cs.ubc.ca/~gregor/) used it for a conference tutorial I attended a few years ago, so that's a sort of implicit seal of approval from him as well. On the other hand, he did point out that it couldn't handle all the examples he showed in his paper (which were implemented in Lisp).
I was not impressed by the various AOP libraries for .NET when I looked at them several years ago. They imposed so many requirements on my code that it seemed to defeat much of the benefit of AOP's beautifully elegant combination of joinpoints and advice.
A problem with AspectJ and I suspect with most implementations is that weaving and optimization can conflict. For example, if a method invocation is inlined by a compiler, the compiler needs to know about applicable advice. This complicates pointcuts and it means that AspectJ can't necessarily be used like dtrace to instrument code you didn't write.
I think a better question would be, do any languages have features that help _you_ follow an aspect-oriented paradigm? At the end of the day, you can use just about any paradigm in Java. By no means does it enforce OO. Ditto for just about any other language. But certain features make it easy to use OO, so when using it, you feel compelled to use that paradigm.