Declarative Programming in Java

來源:互聯網
上載者:User

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 

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 extends Annotation> annotationType)

    Returns true if an annotation for the specified type is present on this element, elsefalse. 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:

  1. java.lang.reflect.AccessibleObject
  2. java.lang.Class
  3. java.lang.reflect.Constructor
  4. java.lang.reflect.Field
  5. java.lang.reflect.Method
  6. 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.TestRunner Example, the output looks like the following:

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

Pages: 1, 2, 3

Next Page

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.