您的位置:首页 > 编程语言 > Java开发

Declarative Programming in Java

2009-07-29 22:49 344 查看
public static interface PublicMethod
       extends Annotation
   {
   }
   public static interface PrivateMethod
       extends Annotation
   {
   }
上面是Palm里面用到的Annotation,特转载下面一篇文章(http://www.ericdlarson.com/misc/chrome_command_line_flags.html)。
 

Declarative Programming in Java

by Narayanan Jayaratchagan
04/21/2004 What makes EJB components special is the declarative programming model through which we can specify the services such as security, persistence, transaction etc., that the container should provide. An EJB only implements the business logic; the services are associated through a deployment descriptor, which essentially acts as metadata for the EJB. At runtime, the container uses the metadata specified in the deployment descriptor to provide the services. The deployment descriptor is an XML file, not part of the Java classes that make up the EJBs. Is there a standard way to annotate the Java classes that make up the EJBs so that a developer can look at the class definition, together with annotations, and know everything about that class? It would be even better if the remote, home interfaces and the deployment descriptor could be automatically generated by a tool using the annotations. Better yet, can we provide the same kind of declarative services for a simple Java object? If so, how? This article examines how JSR-175: A Metadata Facility for the Java Programming Language will help us in finding answers to these questions and more.
Approaches to Programming There are two approaches to programming called imperative programming and declarative programming. Imperative programming gives a list of instructions to execute in a particular order -- Java program that counts the number of words in a text file is an example of the imperative approach. Declarative programming describes a set of conditions, and lets the system figure out how to fulfill them. The SQL statement
SELECT COUNT(*) FROM XYZ
is an example for the declarative approach. In other words, "specifying how" describes imperative programming and "specifying what is to be done, not how" describes declarative programming.
Annotations The Tiger release of Java (JDK 1.5) adds a new language construct called annotation (proposed by JSR-175). Annotation is a generic mechanism for associating metadata (declarative information) with program elements such as classes, methods, fields, parameters, local variables, and packages. The compiler can store the metadata in the class files. Later, the VM or other programs can look for the metadata to determine how to interact with the program elements or change their behavior.
Declaring an Annotation Declaring an annotation is very simple -- it takes the form of an interface declaration with an
@
preceding it and optionally marked with meta-annotations, as shown below:
package njunit.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface UnitTest {
	String value();
}


The
Retention
meta-annotation declares that the
@UnitTest
annotation should be stored in the class file and retained by the VM so it may be read reflectively. The
Target
meta-annotation declares that the
@UnitTest
annotation can be used to annotate methods in a Java class.
@interface
declares the
@UnitTest
annotation with one member called
value
, which returns a
String
.

Using an Annotation

Here is an example that shows how to use the
@UnitTest
annotation declared in the previous section:

import njunit.annotation.*;

public class Example {

    @UnitTest(value="Test 1. This test will pass.")
    public void pass() {
        assert 10 > 5;
    }

    @UnitTest("Test 2. This test will fail.")
    public void fail() {
        assert 10 < 5;
    }

}


An annotation is applied to the code element by placing an annotation statement (
@AnnotationType(...)
) before the program element. Annotation values take the form
"name=value"
; for example,
@UnitTest(value="some text")
. Single-member annotations with a member named
value
are treated specially and can use the shorthand
@UnitTest("some text")
. In the example, the
@UnitTest
annotation is associated with the
pass
and
fail
methods.

 

Accessing Annotations at Runtime

Once annotations have been associated with program elements, we can use reflection to query their existence and get the values. The main reflection methods to query annotations are in a new interface:
java.lang.reflect.AnnotatedElement
.

Methods available in the
AnnotatedElement
interface are:


boolean isAnnotationPresent(Class annotationType)



Returns
true
if an annotation for the specified type is present on this element, else
false
. This method is designed primarily for convenient access to marker annotations.




T getAnnotation(Class annotationType)



Returns this element's annotation for the specified type if such an annotation is present, else null.




Annotation[] getAnnotations()



Returns all annotations present on this element. (Returns an array of length zero if this element has no annotations.)




Annotation[] getDeclaredAnnotations()



Returns all annotations that are directly present on this element. Unlike the other methods in this interface, this method ignores inherited annotations. (Returns an array of length zero if no annotations are directly present on this element.)



You may notice that the
isAnnotationPresent
and
getAnnotation
methods are defined using generics, another new feature available in JDK 1.5.

Here is the list of classes that implement the
AnnotatedElement
interface:

java.lang.reflect.AccessibleObject


java.lang.Class


java.lang.reflect.Constructor


java.lang.reflect.Field


java.lang.reflect.Method


java.lang.Package


Next, I'll show you an example that illustrates how to access annotations at runtime.

package njunit;

import java.lang.reflect.*;
import njunit.annotation.*;

public class TestRunner{
    static void executeUnitTests(String className) {
        try {
            Object testObject =
                Class.forName(className).newInstance();
            Method [] methods =
                testObject.getClass().getDeclaredMethods();
            for(Method amethod : methods) {
            UnitTest utAnnotation =
                amethod.getAnnotation(UnitTest.class);
            if(utAnnotation!=null) {
                System.out.print(utAnnotation.value() +
                                " : " );
                String result =
                    invoke(amethod, testObject);
                System.out.println(result);
                }
            }
        }catch(Exception x) {
            x.printStackTrace();
        }
    }
    
    static String invoke(Method m, Object o) {
        String result = "passed";
        try{
            m.invoke(o,null);
        } catch(Exception x) {
            result = "failed";
        }
        return result;
    }
    
    public static void main(String [] args) {
        executeUnitTests(args[0]);
    }
}


The
TestRunner
uses the
@UnitTest
annotation to determine whether a method is a unit test or not, invoke the method if it is marked with the
@UnitTest
annotation, and report the success or failure.

Here is how the
TestRunner
executes the unit test. Given a Java class, the
TestRunner
first obtains the list of all declared methods using reflection. Then it queries each method using the enhanced
for
construct and the
getAnnotation
method available in JDK 1.5 to find out whether it is marked as a
@UnitTest
. If it is marked, then it invokes the method and reports the success or failure. A test is considered failed if there is any exception when executing the test, and is considered passed otherwise.

In our
Example
class, the
pass
method will succeed when invoked, but the
fail
method will throw an
AssertionError
, which is propagated to the
TestRunner.invoke
method as
InvocationTargetException
.

When run with the command
java -ea njunit.TestRunnerExample
, the output looks like the following:

Test 1. This test will pass. : passed
Test 2. This test will fail. : failed


Pages: 1, 2, 3

Next Page

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: