Why Getting Spring Beans in Non‑Spring Classes Causes NullPointerExceptions
This article explains why retrieving Spring beans from classes not managed by Spring can cause NullPointerExceptions and failed autowiring, demonstrates two code examples—using a utility class and @Autowired in a plain class—and recommends registering such classes as Spring components to ensure proper dependency management.
In non‑Spring‑managed classes, retrieving Spring beans can cause issues such as NullPointerExceptions and failed autowiring.
Case 1
Utility class SpringContextUtils provides a way to obtain beans from the application context.
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
// Ensure the Spring container is initialized before using this utility,
// otherwise a NullPointerException may be thrown.
return applicationContext.getBean(clazz);
}
}Plain class using the utility:
public class PlainClass {
public void foo1() {
TheOtherBean bean = SpringContextUtils.getBean(TheOtherBean.class);
System.out.println(bean);
}
}Calling foo1 from a Spring bean works, but calling it from a non‑Spring class throws a NullPointerException because SpringContextUtils is not managed and its applicationContext is null.
Case 2
Plain class with an @Autowired field:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
public class PlainClass {
@Autowired
private TheOtherBean theOtherBean;
public void foo2() {
System.out.println(theOtherBean);
}
}
@Component
public class TheOtherBean { }When foo2 is invoked from a Spring bean, the output is null because PlainClass is not a Spring component, so the autowired field is not injected.
The IDE warns: “Autowired members must be defined in valid Spring bean (@Component|@Service|…)”.
Executing the same call from a non‑Spring class also yields null.
Test class
package jstudy.beantest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
@RunWith(SpringRunner.class)
public class BeanTest {
@Test
public void test() {
new PlainClass().foo2();
}
}Removing @SpringBootTest and @RunWith turns BeanTest into a plain Java class, i.e., a non‑Spring bean.
Summary
Directly obtaining Spring beans in non‑Spring classes can lead to NullPointerExceptions and failed autowiring. The recommended practice is to register any class that needs to access Spring beans as a Spring component so that dependencies are managed correctly.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Captain
Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
