注意:这不是 Spring 的预期使用方式,并且会产生严重的副作用(难以解决的错误等)。请尝试重构您的代码以使其不再需要它!
通用解决方案
您可以创建一个允许从静态上下文访问任何 Bean 的类。这里的大多数其他答案仅显示如何静态访问单个类。
添加了下面代码中的代理,以防有人在自动装配 ApplicationContext 之前调用 getBean() 方法(因为这会导致空指针)。此处发布的其他解决方案均未处理该空指针。
我的博客上的详细信息:https ://tomcools.be/post/apr-2020-static-spring-bean/
用法
UserRepository userRepo = StaticContextAccessor.getBean(UserRespository.class)
StaticContextAccessor 的完整代码:
@Component
public class StaticContextAccessor {
private static final Map<Class, DynamicInvocationhandler> classHandlers = new HashMap<>();
private static ApplicationContext context;
@Autowired
public StaticContextAccessor(ApplicationContext applicationContext) {
context = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
if (context == null) {
return getProxy(clazz);
}
return context.getBean(clazz);
}
private static <T> T getProxy(Class<T> clazz) {
DynamicInvocationhandler<T> invocationhandler = new DynamicInvocationhandler<>();
classHandlers.put(clazz, invocationhandler);
return (T) Proxy.newProxyInstance(
clazz.getClassLoader(),
new Class[]{clazz},
invocationhandler
);
}
//Use the context to get the actual beans and feed them to the invocationhandlers
@PostConstruct
private void init() {
classHandlers.forEach((clazz, invocationHandler) -> {
Object bean = context.getBean(clazz);
invocationHandler.setActualBean(bean);
});
}
static class DynamicInvocationhandler<T> implements InvocationHandler {
private T actualBean;
public void setActualBean(T actualBean) {
this.actualBean = actualBean;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (actualBean == null) {
throw new RuntimeException("Not initialized yet! :(");
}
return method.invoke(actualBean, args);
}
}
}