[!NOTE] We touched upon Annotations briefly with
@Override. But Annotations govern modern Java frameworks entirely. If you want to use Spring or Hibernate, you must understand exactly how decorators inject massive amounts of hidden logic!
What is an Annotation?
An annotation (the @ symbol followed by a name) is Metadata. It does not perform any physical logic by itself. It is simply a tag stitched onto a class or method.
@Deprecated // Warning! Do not use this method anymore!
public void oldLegacyLogin() { ... }
How Frameworks Use Annotations (Reflection)
If an annotation is just a descriptive label, how does the famous Spring Framework use @RestController to magically launch a Tomcat web server and start mapping HTTP requests?
It uses Reflection.
Java Reflection is an incredibly dangerous, ultra-powerful API that allows the Java JVM to look in the mirror. It lets code inspect itself while it is actively running.
- The Spring Framework starts up.
- It uses Reflection to aggressively scan every single Class in your entire
/srcdirectory. - It asks: "Does this Class have the
@RestControllertag glued to it?" - If Yes, Spring dynamically hijacks the class, generates a massive proxy server block in memory, injects JSON parsing logic, and opens ports to the internet!
// Without you writing ANY server code, Spring detects this tag and boots a server for it via Reflection!
@RestController
public class AuthenticationAPI {
// Spring scans for this tag, and routes HTTP GET requests straight into your method!
@GetMapping("/login")
public String attemptLogin() {
return "You have reached the API!";
}
}
[!CAUTION] Applying Reflection directly yourself (like invoking methods via string names) is extremely slow and breaks compile-time safety. Unless you are literally building the next Spring Boot framework yourself, avoid utilizing the
java.lang.reflectpackage in business logic!
Annotations Need Something to Read Them
An annotation is metadata. It becomes powerful only when a compiler, framework, test runner, or runtime scanner reads it and acts on it. @Override is read by the compiler. Spring annotations are read by Spring.
Custom Annotation Shape
@interface AuditLog {
String action();
}
@AuditLog(action = "CREATE_USER")
void createUser() {
// business logic
}
By itself this does nothing. Some code must inspect the method and react to @AuditLog.
Reflection Tradeoff
Reflection is powerful for frameworks, serializers, dependency injection, and test tools. In everyday business code, prefer normal method calls because they are safer, faster, and easier for IDEs to refactor.
Common Mistakes
- Assuming an annotation automatically performs behavior.
- Using reflection where a normal interface would be simpler.
- Accessing private fields reflectively and breaking encapsulation.
- Forgetting that reflection errors often appear at runtime, not compile time.
Mini Practice
Create a custom marker annotation called Important. Add it to two methods. Then describe what kind of framework behavior could scan for it.
Practice Lab: Annotation Thinking
Annotations are metadata, so practice designing one and explaining who would read it.
- Create an annotation named
Important. - Add it to two methods.
- Create a second annotation named
AuditLogwith anactionvalue. - Add
@AuditLog(action = "CREATE_USER")to a method. - Write a comment explaining what a framework could do after finding that annotation.
Goal: Understand that annotations mark code; separate tooling or framework code gives them meaning.
Revision Checkpoint
- Annotation: Metadata attached to code.
- Framework role: External code reads annotations and acts on them.
@Override: Compiler-checked annotation.- Reflection: Runtime inspection of classes, methods, and fields.
- Caution: Reflection can weaken compile-time safety and performance.
Before the quiz: Explain why an annotation alone does not perform behavior.