Sitemap
Press enter or click to view image in full size

Spring , CDI , EJB Annotations

--

If you’ve spent more than 15 minutes in enterprise Java, you’ve probably seen annotations like:

@Autowired
@Inject
@Resource
@EJB
@ApplicationScoped
@Service
@Component
@Stateless

…and immediately wondered:

“Why are there so many ways to inject the same object?”

Welcome to enterprise Java.

The good news?
Once you understand what category these annotations belong to, everything suddenly becomes much simpler.

This article will save you from:

  • memorizing random annotations
  • confusing CDI with Spring
  • pretending to understand EJB during interviews
  • opening StackOverflow tabs at 2AM

Let’s make sense of this mess.

There Are ONLY 2 Things Happening

Almost every annotation in this area belongs to one of two buckets:

Dependency Injection: “How do I get this object?”

Scope/Bean Lifecycle: “How long does this object live?”

That’s it. Once you separate these mentally, enterprise Java becomes 10x easier.

Part 1 — Dependency Injection Annotations

These annotations basically say:

“Hey framework, give me this dependency.”

Like ordering coffee from the container.

@Autowired — Spring’s Famous Magic Wand

If Spring had a mascot, it would probably be @Autowired.

@Autowired
private UserService userService;

Spring sees this and goes:

“Cool, I’ll find a UserService bean for you.”

By default:

  • injection happens by type

Meaning:

UserService

not by variable name.

The Problem: Multiple Beans

Suppose you have:

@Component
class StripePaymentService implements PaymentService {}

and:

@Component
class PaypalPaymentService implements PaymentService {}

Now Spring panics:

“WHICH ONE DO YOU WANT???”

That’s where @Qualifier comes in:

@Autowired
@Qualifier("stripePaymentService")
private PaymentService service;

Now Spring can sleep peacefully again.

Modern Spring Developers Quietly Avoid @Autowired

Plot twist.

Modern Spring code often doesn’t even use it.

Instead:

@Service
public class OrderService {

private final PaymentService paymentService;

public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
}

This is called constructor injection.

And honestly?It’s cleaner, safer, easier to test, and less magical.

Spring automatically injects it. No annotation needed.

@Inject — The “Standard Java” Version

Now imagine someone at Java HQ said:

“Maybe dependency injection should become standardized.”

So CDI/Jakarta EE introduced:

@Inject
private UserService userService;

Functionally, this is VERY similar to @Autowired.

Think of it as:

SpringJakarta/CDI@Autowired@Inject

Same idea. Different family.

@Resource — The Old School One

@Resource comes from older Java EE traditions.

@Resource
private DataSource dataSource;

Unlike @Autowired, this one usually injects:

  • by name first
  • then maybe by type

So if your field is:

private DataSource mainDb;

the container tries finding a bean literally called:

mainDb

This was super common for:

  • databases
  • JMS queues
  • infrastructure resources

Very enterprise-y…. Very 2009.

@EJB — The Ancient Beast

Ah yes. EJB.

The annotation developers fear during interviews.

@EJB
private PaymentService paymentService;

Back in the day, EJBs were THE enterprise solution.

Get Tafsir’s stories in your inbox

Join Medium for free to get updates from this writer.

They handled:

  • transactions
  • remoting
  • pooling
  • security
  • lifecycle management

Basically:

“What if XML became a framework?”

Modern Spring replaced most EJB use cases with:

@Service
@Transactional

Much lighter. Much saner. Far fewer therapy sessions.

@PersistenceContext — JPA’s Special Injection

This one injects the JPA EntityManager.

@PersistenceContext
private EntityManager em;

Think of it as:

“Give me database superpowers.”

In Spring, people often just do:

@Autowired
private EntityManager em;

and Spring handles the rest.

Part 2 — Scope & Lifecycle Annotations

Now we move to the SECOND category. These annotations answer:

“What kind of bean is this?” “How long should it live?”

@Component — The Generic Spring Bean

@Component
public class UserService {
}

This tells Spring:

“Manage this class.”

That’s all. By default:

  • Spring creates ONE instance
  • application-wide singleton

Spring’s Fancy Variants

Spring later added more descriptive versions:

AnnotationMeaning@ComponentGeneric bean@ServiceBusiness logic@RepositoryDatabase layer@ControllerMVC controller@RestControllerREST API controller

Technically similar. But semantically cleaner.

@ApplicationScoped — CDI’s Singleton

CDI equivalent:

@ApplicationScoped
public class UserService {
}

Meaning:

“One contextual instance for the entire application lifecycle.”

Conceptually similar behavior as Spring singleton beans.

@RequestScoped — One Bean Per Request

Every HTTP request gets a fresh object.

Useful for:

  • request-specific state
  • temporary data
  • web request processing

CDI:

@RequestScoped

Spring:

@RequestScope

@SessionScoped — One Bean Per User Session

Useful for:

  • shopping carts
  • login state
  • user preferences

Just don’t abuse it. Otherwise your memory usage becomes:

“surprise production outage.”

@Stateless — The EJB Business Bean

@Stateless
public class PaymentService {
}

This means:

  • no conversational state
  • pooled instances
  • transactional service

Think of it as enterprise-grade service objects.

Modern Spring equivalent is roughly:

@Service
@Transactional

Not identical.
But philosophically similar.

The Cheat Sheet Everyone Actually Wants

Press enter or click to view image in full size

The Important Thing Most Tutorials Never Explain

These are NOT competing annotations. This is wrong thinking:

@Autowired vs @ApplicationScoped

That’s like comparing:

“car engine” with “parking duration”

Correct comparison:

@Autowired vs @Inject

and:

@Component vs @ApplicationScoped

THAT is the real mapping.

Conclusion

Enterprise Java looks terrifying but underneath all the chaos, the concepts are surprisingly simple:

  • inject dependencies
  • manage object lifecycle
  • organize application layers

Once you separate those ideas, the annotation jungle suddenly turns into a small map instead of a horror movie.

--

--