Backend Development 6 min read

Spring Dependency Injection Tricks: Optional, Provider, Collections, @Value & @Lazy

This article demonstrates various Spring dependency‑injection techniques—including Optional, ObjectProvider, Provider, arrays, collections, maps, @Value literals and SpEL expressions, as well as @Lazy proxies—showing the code and resulting bean representations for each approach.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Dependency Injection Tricks: Optional, Provider, Collections, @Value & @Lazy

Environment: Spring 5.3.23 (Java 1.8).

1. Optional

java.util.Optional<T> can be injected to lazily obtain a bean.

<code>static class CommonDAO {}
static class CommonService {
  @Resource
  private Optional<CommonDAO> optional;
  @Override
  public String toString() {
    return "CommonService [optional=" + optional.orElseGet(() -> null) + "]";
  }
}
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonDAO.class, CommonService.class)) {
  System.out.println(context.getBean(CommonService.class));
}
</code>

Output:

<code>CommonService [optional=xxx.CommonDAO@12d4bf7e]</code>

2. ObjectFactory (ObjectProvider)

Spring’s ObjectProvider can be used to obtain a bean when needed.

<code>static class CommonService {
  @Resource
  private ObjectProvider<CommonDAO> provider;
  @Override
  public String toString() {
    return "CommonService [provider=" + provider.getIfAvailable() + "]";
  }
}
</code>

Output:

<code>CommonService [provider=xxx.CommonDAO@11a9e7c8]</code>

3. Provider (javax.inject.Provider)

javax.inject.Provider offers a standard way to retrieve a bean.

<code>static class CommonService {
  @Resource
  private javax.inject.Provider<CommonDAO> provider;
  @Override
  public String toString() {
    return "CommonService [provider=" + provider.get() + "]";
  }
}
</code>

Output:

<code>CommonService [provider=xxx.CommonDAO@2f177a4b]</code>

Note: If javax.inject.Provider is missing, add the following Maven dependency:

<code>&lt;dependency&gt;
  &lt;groupId&gt;javax.inject&lt;/groupId&gt;
  &lt;artifactId&gt;javax.inject&lt;/artifactId&gt;
  &lt;version&gt;1&lt;/version&gt;
&lt;/dependency&gt;
</code>

4. Array Injection

<code>static interface DAO {}
static class DogDAO implements DAO {}
static class CatDAO implements DAO {}
static class CommonService {
  @Resource
  private DAO[] daos;
  @Override
  public String toString() {
    return "CommonService [daos=" + Arrays.toString(this.daos) + "]";
  }
}
</code>

Output:

<code>CommonService [daos=[xxx.DogDAO@4445629, xxx.CatDAO@45b9a632]]</code>

5. Collection Injection (List)

<code>static class CommonService {
  @Resource
  private List<DAO> daos;
  @Override
  public String toString() {
    return "CommonService [daos=" + daos + "]";
  }
}
</code>

Output:

<code>CommonService [daos=[xxx.DogDAO@309e345f, xxx.CatDAO@56a6d5a6]]</code>

6. Map Injection

<code>static class CommonService {
  @Resource
  private Map<String, DAO> daos;
  @Override
  public String toString() {
    return "CommonService [daos=" + daos + "]";
  }
}
</code>

Output:

<code>CommonService [daos={dataTypeInejctMain.DogDAO=xxx.DogDAO@4445629, dataTypeInejctMain.CatDAO=xxx.CatDAO@45b9a632}]</code>

7. Special Cases

7.1 Using @Value

Injecting literal values:

<code>static class CommonService {
  @Value("${pack.name}")
  private String name;
  @Override
  public String toString() {
    return "CommonService [name=" + name + "]";
  }
}
// property file
pack.name=中国🇨🇳
</code>

Output:

<code>CommonService [name=中国🇨🇳]</code>

Injecting via SpEL expression:

<code>static class CommonService {
  @Value("#{${pack.name}}")
  private CommonDAO dao;
  @Override
  public String toString() {
    return "CommonService [name=" + dao + "]";
  }
}
// property
pack.name=commonDao
// register bean
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
  context.registerBean("commonDao", CommonDAO.class);
  context.register(CommonService.class);
  System.out.println(context.getBean(CommonService.class));
}
</code>

Output:

<code>CommonService [name=xxx.CommonDAO@29176cc1]</code>

Injecting basic data types (automatic conversion):

<code>static class CommonService {
  @Value("666")
  private int id;
  @Override
  public String toString() {
    return "CommonService [id=" + id + "]";
  }
}
</code>

Output:

<code>CommonService [id=666]</code>

7.2 Using @Lazy

@Lazy creates a proxy; the actual bean is instantiated only when accessed.

<code>static class CommonService {
  @Resource
  @Lazy
  private CommonDAO commonDao;
  @Override
  public String toString() {
    return "CommonService [commonDao=" + commonDao.getClass() + "]";
  }
}
</code>

Output:

<code>CommonService [commonDao=class xxx.CommonDAO$$EnhancerBySpringCGLIB$$39f36385]</code>

These examples cover the most common ways to inject dependencies in Spring, helping developers choose the appropriate technique for their use case.

JavaSpringdependency injectionOptional@ValueProviderLazyObjectProvider
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.