from http://www.jroller.com/page/ara_e/20031108#jsr175_thoughts

Ok, I finally read the public draft for JSR 175. Generally it's ok but there are some flaws and limitations, imho:

Why annotation types are interfaces and not regular classes?! .Net Annotations types are normal classes. Normal classes are better for annotation types because, you know, you can put code in a real class, but in an interface you just define stuff! Being interface-based leads to some limitations: for example if you want to define a Factor annotation type and the value should be a float value in 0.0 to 1.0 range you just can't do that, you can't write a piece of code to check that the annotation declared by user is valid. I think annotations are a declarative way of defining metadata, right? So the annotation should also be checked/validated where it's declared in the code, not during runtime when a piece of code finally uses it!

Also another related limitation is that you can't define helper methods, so if one of the annotation type members is a defined as String bugNumber(); and valid values are either "[unassigned]" or an integer value in that String and you access the bugNumber value and it's a String and you should do Integer.valueOf() to convert the value to integer if it's not "[unassigned]", in your own client code or in a helper class supplied with the jar containing the annotation type. If annotation type were normal classes you could just add a getBugNumberInt() method to the annotation class.

So with this interface based approach basically validation of what the user of an annotation puts into a declaration is vastly limited, limited to int/boolean/etc type checks and enums, and nothing more. What if a poor developer puts an annotation which is only appropriate for a SLSB ejb on a SFSB for example? I think the poor developer would wonder why his correct annotation is not used at all! Guys, these kinds of scenarios do happen a lot in the real world! Just look at the archives for xdoclet-user mailing list. People do use @tags in incorrect places and pull their hair out wondering why it doesn't work! Would be a good idea to add the possibility to indicate that annotation type X can be applied only to a class derived from type Y (a mechanism like the @Target tag, but more flexible and applicable to members too). So EjbFinder can only be put on an EntityBean-derived class, and need I say only if the class also has a @Ejb annotation?

Unfortunately there's no support for attribute subclassing. There are more than just 3-4 @annotations in the real world that contain common fields! Just look at ejb related attributes for example. ejb-name, ejb-ref-name, many other parameters. Weird limitation....

Another very strange limitation is that apparently you can apparently define only a single instance of an annotation type for a program element. So you can't define many @EjbFinder or @EjbRef tags for a class. The reflection side is limited to returning only a single instance for an annotation type:

AnnotatedElement: <T extends Annotation> T getAnnotation(Class<T> annotationType);

Can't do getAnnotations(EjbFinder.class) and get ALL finders declared for the class!

I'm glad that you can put annotation declarations inside annotation declarations. This is useful for ejb. So let's say there's a generic @EjbFinder defined for a class and it contains the finder signature and the generic EJBQL. Different app server have different EJBQL extensions, so we add a @WebLogicFinderQuery just below the @EjbFinder and define the app-server specific one there. With annotation declaration inside annotation declaration it's possible to bind these two to each other elegantly:

@EjbFinder(signature="java.util.List findBla()", @WebLogicFinderQuery("select blabla weblogic specific"))

I'm not sure it's still an elegant syntax for binding many related custom query @annotations to an annotation in form of an array or if it's possible at all:

@EjbFinder(signature="java.util.List findBla()", {@WebLogicFinderQuery("select blabla weblogic specific"), @JBossFinderQuery("select blabla jboss specific")})

Hmm....

Also I was hoping that the expert group would have defined a richer runtime API. Annotations.getClassWithAnnotationTypeOf(Class annotationType), Class.getMethodsWithAnnotation(Class annotationType), and such method. .Net has a far richer runtime API, support for wildcards and many goodies and convenience methods, and none of the limitations that I described above.

And finally I'm not sure the spec is friendly to compile time tools such as XDoclet or UML diagram tools. Generating stub like classes for Annotation is not a beautiful solution.

I think it's not possible in any way to use this spec in JDKs prior to JDK 1.5, neither legally nor technically. It's bound to generics, enums and other JDK1.5 specific stuff. We have to wait for JDK 1.5....

Comments, thoughts and corrections are welcome....

PS: Imho the best way to write a spec is to TDD it :-) Start from EJB, define annotations for it, see what a complex system like EJB needs, now go write a spec that satisfies those inhumane needs. It's real world with this approach.

Ara.

posted on 2004-08-27 20:06  taowen  阅读(543)  评论(0)    收藏  举报