Since the introduction of the annotations in Java 5.0 version, it has become a very important part of the Java platform. During the development process, we often see annotations such as @Override and @Deprecated in the application code. In this article, I will tell you what annotations are, why they should be introduced, how annotations work, how to write custom annotations (through examples), and under what circumstances can you use annotations as well as the latest annotations and ADF (application development framework). It will take a little time, so prepare yourself a cup of coffee and let us enter the world of annotation.
What is annotation?
One word can describe annotations, that is metadata, that is, data that describes data. Therefore, it can be said that the annotation is the metadata of the source code. For example, the following code:
@Overridepublic String toString() { return "This is String Representation of current object.";}In the above code, I rewrite the toString() method and use the @Override annotation. However, even if I don't use @Override annotation to mark the code, the program can execute normally. So, what does the annotation mean? Is there any benefit to writing this way? In fact, @Override tells the compiler that this method is a rewrite method (metadata describing the method). If the method does not exist in the parent class, the compiler will report an error, prompting that the method does not rewrite the method in the parent class. If I accidentally spell the wrong typo, for example, write toString() as toString(){double r}, and I don't use the @Override annotation, the program can still be compiled and run. But the results of the operation will be very different from what I expected. Now we understand what annotations are, and using annotations helps read the program.
Annotation is a special modifier applied to classes, methods, parameters, variables, constructors and package declarations. It is a tool selected by the JSR-175 standard to describe metadata.
Why introduce annotations?
Before (or even after use), XML is widely used to describe metadata. Some application developers and architects have begun to find that the maintenance of XML is getting worse and worse. They want to use something tightly coupled to the code, rather than a code description that is loosely coupled to the code (and in some cases even completely separate) like XML. If you search for "XML vs. annotations" in Google, you will see many debates on this issue. The most interesting thing is that XML configuration is actually introduced to separate code and configuration. The above two views may confuse you. Both views seem to form a cycle, but each has its pros and cons. Let’s use an example to understand the difference between the two.
If you want to set a lot of constants or parameters for your application, XML is a good choice in this case because it will not be connected to specific code. If you want to declare a method as a service, it would be better to use Annotation because in this case, the annotation and method need to be tightly coupled, and developers must recognize this.
Another important factor is that Annotation defines a standard way of describing metadata. Before this, developers usually define metadata in their own way. For example, use tagged interfaces, annotations, transient keywords, and so on. Each programmer defines metadata in his own way, unlike Annotation's standard way.
Currently, many frameworks use XML and Annotation in combination to balance the pros and cons between the two.
How does Annotation work? How to write a custom Annotation?
Before telling this part, we recommend that you first download the Annotations sample code AnnotationsSample.zip. After downloading, put it in the IDE you are used to using. These codes will help you better understand the Annotation mechanism.
Writing Annotation is very simple, you can compare the definition of Annotation with the definition of interface. Let's look at two examples: one is the standard annotation @Override, and the other is the user-defined annotation @Todo.
@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override {}You may have some questions about the @Override annotation, it does nothing, so how does it check that there is a function with the same name in the parent class? Of course, don't be surprised, I'm just teasing you. The definition of @Override annotation is not just that little code. This part of the content is very important, I have to repeat it again: Annotations is just metadata and has nothing to do with business logic. It's a bit difficult to understand, but that's it. If Annotations does not contain business logic, someone must implement them. Metadata users do this. Annotations only provides information on the properties it defines (class/method/package/domain). Annotations' users (again, some code) read this information and implement the necessary logic.
When we use Java's annotations (such as @Override), the JVM is a user, which works at the bytecode level. At this point, application developers cannot control or use custom annotations. So, let's explain how to write custom Annotations.
Let's talk about the key points of writing custom Annotations one by one. In the example above, you see some annotations applied to the annotations.
The J2SE5.0 version provides four kinds of meta annotations in java.lang.annotation, which specifically annotates other annotations:
@Documented A simple Annotations tag annotation indicating whether annotation information is added to the java document.
@Retention defines the life cycle of this annotation.
RetentionPolicy.SOURCE is discarded during the compilation phase. These annotations no longer have any meaning after compilation, so they do not write bytecode. @Override, @SuppressWarnings all belong to this type of annotation.
RetentionPolicy.CLASS is discarded when the class is loaded. Useful in processing bytecode files. This is the default method for annotations.
RetentionPolicy.RUNTIME is never discarded, and the annotation is retained during the runtime, so the information of the annotation can be read using the reflection mechanism. Our custom annotations are usually used this way.
@Target indicates where this annotation is used. If not specified, the annotation can be placed anywhere. Here are some of the available parameters. It should be noted that the annotation of attributes is compatible. If you want to add annotation to all 7 attributes and only exclude one attribute, then you need to define the target to include all attributes.
@Inherited defines the relationship between this annotation and subclasses
So, how is the internal definition of annotations? Annotations only supports basic types, String and enum types. All attributes in the comment are defined as methods and allow default values to be provided.
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@interface Todo {public enum Priority {LOW, MEDIUM, HIGH}public enum Status {STARTED, NOT_STARTED}String author() default "Yash";Priority priority() default Priority.LOW;Status status() default Status.NOT_STARTED;} The following example demonstrates how to use the above annotations.
@Todo(priority = Todo.Priority.MEDIUM, author = "Yashwant", status = Todo.Status.STARTED)public void incompleteMethod1() {//Some business logic is written//But it's not complete yet} If there is only one attribute in the annotation, it can be named directly "value", and there is no need to indicate the attribute name when using it.
@interface Author{String value();}@Author("Yashwant")public void someMethod() {} But so far everything looks pretty good. We define our own annotations and apply them to business logic methods. Now we need to write a user program to call our annotation. Here we need to use the reflection mechanism. If you are familiar with reflection code, you will know that reflection can provide class names, methods, and instance variable objects. All these objects have the getAnnotation() method to return annotation information. We need to convert this object into our custom comment (after checking with instanceOf()), and we can also call the methods in the custom comment. Take a look at the following example code, using the above annotation:
Class businessLogicClass = BusinessLogic.class;for(Method method: businessLogicClass.getMethods()) {Todo todoAnnotation = (Todo)method.getAnnotation(Todo.class);if(todoAnnotation != null) {System.out.println(" Method Name : " + method.getName());System.out.println(" Author : " + todoAnnotation.author());System.out.println(" Priority : " + todoAnnotation.priority());System.out.println(" Status : " + todoAnnotation.status());}}Annotation use cases
The functions of annotations are very powerful, and frameworks such as Spring and Hebernate use annotations in logging and validity. Annotations can be applied where marker interfaces are used. The difference is that the tag interface is used to define a complete class, but you can define comments for a single method, such as whether to expose a method as a service.
Many new annotations have been introduced in the latest servlet 3.0, especially those related to servlet security.
HandlesTypes This annotation is used to represent a set of application classes passed to the ServletContainerInitializer.
HttpConstraint This annotation represents the security constraints for application requests of all HTTP methods, and is different from the HttpMethodConstraint security constraints defined in the ServletSecurity annotation.
HttpMethodConstraint specifies security constraints for different types of requests, which are different from the annotation that describes the HTTP protocol method type in the ServletSecurity annotation.
MultipartConfig This annotation is marked on the Servlet, indicating that the MIME type of the request that the Servlet wants to process is multipart/form-data.
ServletSecurity The annotation is marked on the Servlet inheritance class, and the HTTP protocol request is forced to comply with security constraints.
WebFilter is used to declare a Server filter;
WebInitParam This annotation is used to declare the initialization parameters in the Servlet or filter, and is usually used with @WebServlet or @WebFilter.
WebListener This annotation is a different type of event declaration listener in the context of the web application.
WebServlet This annotation is used to declare the configuration of a Servlet.
ADF (Application Framework) and Annotations
Now we start discussing the last part of the article. Application framework, known as ADF, is developed by Oracle to create Oracle converged applications. We have understood the advantages and disadvantages of annotations and know how to write custom annotations, but where should we apply the annotations to? Does ADF provide some plain annotations? A good question, indeed there are some limitations in using annotations in ADF. The previously mentioned application frameworks such as Spring and Hibernate use AOP (side-oriented programming). In AOP, the framework provides a mechanism to inject code into pre-processing and subsequent processing of events. For example: you have a hook to add code before and after method execution, so you can write your user code in these places. ADF does not use AOP. If we have any use cases for annotation available, we may need to implement it through inheritance.
I hope you like this article to help you better understand the meaning of the annotation!