Skip to main content

Command Palette

Search for a command to run...

How Reflection and Annotations Power Spring Boot - Deep Dive into Java's Runtime Magic

Updated
4 min read
How Reflection and Annotations Power Spring Boot - Deep Dive into Java's Runtime Magic
N
Java & Spring Boot learner | Writing beginner-friendly technical articles | Exploring backend development

A deep dive into how Java uses Reflection and Annotations to power modern frameworks like Spring Boot.

When we write Java code, most of the time everything happens at compile time - classes, objects, and method calls are clearly defined.

But have you ever wondered:

  • How does Spring create objects automatically?

  • How does @Autowired work?

  • How does Hibernate map objects to database tables?

  • How do frameworks read annotations?

The answer lies in Reflection and Annotations in Java.

In this article, I'll explain:

  • what Reflection is

  • what annotations are

  • How they work internally

  • How they work together

  • Real-world framework usage

What is Reflection in Java?

Reflection in Java is an API that allows a program to:

  • Inspect classes at runtime

  • Access methods and fields (even private ones)

  • Create objects dynamically

  • Invoke methods dynamically

  • Modify internal state of objects

It is available in:

java.lang.reflect  //package

Why Reflection is important?

Normally in Java:

Student s = new Student();
s.display();

Everything is known at compile time. But using reflection, we can:

  • Load class dynamically

  • Create object without using new

  • Call methods without knowing their names at compile time

This is heavily used in:

  • Spring framework

  • Hibernate ORM

  • JUnit

  • Dependency Injection containers

How to Get Class Object in Java

Reflection starts with the Class class. There are three ways:

Class c1 = Class.forName("com.example.Student");
Class c2 = Student.class;
Class c3 = obj.getClass();

Class.forName()

  • Loads class into JVM

  • Throws ClassNotFoundException

  • Commonly used in JDBC drivers

Creating Objects Using Reflection

Class<T> c = class.forName("Student");
Object obj = c.getDeclaredConstructor().newInstance();

This allows dynamic object creation.

Accessing Private Fields

Field field = c.getDeclaredField("name");
field.setAccessible(true);
field.set(obj, "Nandini");

Reflection can break encapsulation using setAccessible(true).

Invoking Methods Dynamically

Method method = c.getDeclaredMethod("display");
method.setAccessible(true);
method.invoke(obj);

This enables runtime behavior modification.

Disadvantages of Reflection

  • Slower than direct calls

  • Breaks encapsulation

  • Security risks

  • Harder debugging

Therefore, it should be used carefully.

What are Annotations in Java?

Annotations in Java provide metadata about:

  • Classes

  • Methods

  • Fields

  • Parameters

They do not change business logic directly but provide extra information to:

  • Compiler

  • JVM

  • Frameworks

Example:

@Override   // annotation

Built-in Java Annotations

Some commonly used annotations:

//annotations

@Override



@Deprecated



@SuppressWarnings



@FunctionalInterface

Creating Custom Annotation in Java

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation{
    String value();
}

Important Meta-Annotations

@Retention

Defines lifecycle of annotation:

  • SOURCE

  • CLASS

  • RUNTIME

To access annotation using reflection -> use RUNTIME.

@Target

Defines where annotation can be applied:

  • TYPE

  • METHOD

  • FIELD

  • PARAMETER

  • CONSTRUCTOR

@Inherited

Allows child class to inherit annotation.

@Documented

Includes annotation in Javadoc.

How Reflection and Annotations Work Together

This is the most important concept.

Annotations provide metadata. Reflection reads that metadata at runtime.

Example:

Class<T> c = Demo.class;
if(c.isAnnotationPresent(MyAnnotation.class)){
  
   MyAnnotation annotation = c.getAnnotation(MyAnnotation.class);
   System.out.println(annotation.value());
}

Flow:

  1. JVM loads class.

  2. Annotation metadata is stored.

  3. If retention policy is RUNTIME -> it says available.

  4. Reflection reads it.

  5. Program behavior changes dynamically.

How Spring Boot Uses Reflection and Annotations

Spring uses:

. @Component
. @Service
. @Repository
. @Autowired
. @RestController

Spring:

  1. Scans classpath

  2. Detects annotations

  3. Uses reflection

  4. Create objects

  5. Injects dependencies

Without reflection + annotations -> Spring Framework cannot function.

Internal JVM Understanding

When class is compiled:

  • Annotation metadata is stored in bytecode.

  • JVM Keeps it based on retention policy.

  • Reflection API reads metadata.

  • Frameworks act accordingly.

This is how:

  • Dependency Injection works

  • ORM mapping works

  • REST APIs are built

  • AOP Works.

Conclusion

Reflection and Annotations are two of the most powerful features in Java.

Reflection gives Java runtime inspection and dynamic execution capability.

Annotations provide structured metadata to guide behavior. Together they power:

  • Spring Boot

  • Hibernate

  • Testing frameworks

  • Dependency Injection Containers

Mastering these concepts moves a developer from:

Writing Java code -> Understanding how Java frameworks actually work internally.

More from this blog

CoreJava

19 posts

I have written and published a comprehensive blog series titled "CoreJava" on Hashnode, based on my learning journey from basics to advanced. The series includes topics like OOP, Collections, Exception Handling, Multithreading, and Java Streams, explained with clear examples and practical insights to help learners build a strong foundation in java.