Unlock Full Dependency Injection in Spring Boot 3 with Load‑Time Weaving

This article demonstrates how to extend Spring Boot 3's dependency injection to objects created with the new operator by using AspectJ load‑time weaving, @Configurable, META‑INF/aop.xml configuration, and the required -javaagent, providing step‑by‑step code examples and troubleshooting tips.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Unlock Full Dependency Injection in Spring Boot 3 with Load‑Time Weaving

Introduction

In traditional Spring applications, dependency injection (DI) only works for beans managed by the Spring container. When objects are created directly with new —such as domain entities, DTOs, factories, or third‑party callbacks—they fall outside the container and cannot have @Autowired services injected, leading to tight coupling and testing difficulties.

Spring solves this problem with AspectJ load‑time weaving (LTW). By using the @Configurable annotation together with a META‑INF/aop.xml configuration and the -javaagent mechanism, Spring can inject beans into objects instantiated with new, effectively breaking the container boundary.

Step‑by‑Step Implementation

1. Add AspectJ Dependency

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
</dependency>

2. Enable Non‑Managed Bean Injection

@SpringBootApplication
@EnableSpringConfigured
@EnableLoadTimeWeaving
public class App { }

@EnableSpringConfigured signals the context to apply DI to classes annotated with @Configurable. @EnableLoadTimeWeaving activates Spring’s LTW mechanism, allowing AspectJ to enhance bytecode at class‑load time.

3. Define a Non‑Managed Bean

@Configurable
public class CommonService {
    @Resource
    private UserService userService;

    public void getUser() {
        this.userService.query();
    }
}

The @Configurable annotation tells Spring to weave injection logic into CommonService instances created with new. The @Resource field receives the UserService bean from the container.

4. Define the Managed Service

@Service
public class UserService {
    public void query() {
        System.err.println("查询用户信息...");
    }
}

5. Test the Injection

@Component
public class TestRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        CommonService cs = new CommonService();
        cs.getUser();
    }
}

Running the application should print the query message, confirming that UserService was injected into the manually created CommonService.

6. Enable AspectJ Weaving at Runtime

Add the spring-instrument dependency and start the JVM with the agent:

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-instrument</artifactId>
</dependency>

Run with:

-javaagent:D:\java\maven\org\springframework\spring-instrument\6.2.7\spring-instrument-6.2.7.jar

Without the agent you will see an error image:

Missing -javaagent error
Missing -javaagent error

7. Configure aop.xml

<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
  <weaver options="-Xlint:ignore">
    <include within="com.pack..*"/>
  </weaver>
</aspectj>

This file tells AspectJ to weave only classes under com.pack and to suppress warnings.

8. Add a Profiling Aspect

@Aspect
public class ProfilingAspect {
    @Around("methodsToBeProfiled()")
    public Object profile(ProceedingJoinPoint pjp) throws Throwable {
        StopWatch sw = new StopWatch(getClass().getSimpleName());
        try {
            sw.start(pjp.getSignature().getName());
            return pjp.proceed();
        } finally {
            sw.stop();
            System.err.println(sw.prettyPrint());
        }
    }

    @Pointcut("execution(public * com.pack..*.*(..))")
    public void methodsToBeProfiled() {}
}

9. Register the Aspect in aop.xml

<aspectj>
  <weaver options="-Xlint:ignore">
    <include within="com.pack..*"/>
  </weaver>
  <aspects>
    <aspect name="com.pack.mgr.aspect.ProfilingAspect"/>
  </aspects>
</aspectj>

10. Run and Verify

After adding the agent and the aop.xml configuration, the application starts without the previous error. Console output shows profiling information and confirms that the CommonService instance received the UserService bean.

Successful startup log
Successful startup log

Conclusion

The article walks through the complete setup of Spring Boot 3 load‑time weaving, enabling true full‑chain dependency injection for objects created outside the Spring container, and provides practical code snippets, configuration files, and troubleshooting guidance.

backend developmentSpring Bootdependency-injectionaspectjjava-agentLoad-Time Weaving
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

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.