小编典典
SpringBeanAutowiringSupport推荐使用扩展方法,从当前的Spring根Web应用程序上下文中为JAX-
WS端点类注入bean。但是,这不适用于 spring boot,
因为它在servlet上下文初始化方面有些不同。
问题
SpringBootServletInitializer.startup()使用自定义ContextLoaderListener,并且不会将创建的应用程序上下文传递给ContextLoader。稍后,当初始化JAX-
WS端点类的对象时,SpringBeanAutowiringSupport依赖于ContextLoader检索当前应用程序上下文,并始终获取null。
public abstract class SpringBootServletInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext rootAppContext = createRootApplicationContext(
servletContext);
if (rootAppContext != null) {
servletContext.addListener(new ContextLoaderListener(rootAppContext) {
@Override
public void contextInitialized(ServletContextEvent event) {
// no-op because the application context is already initialized
}
});
}
......
}
}
解决方法
您可以注册一个实现org.springframework.boot.context.embedded.ServletContextInitializer了在期间检索应用程序上下文的bean
startup()。
@Configuration
public class WebApplicationContextLocator implements ServletContextInitializer {
private static WebApplicationContext webApplicationContext;
public static WebApplicationContext getCurrentWebApplicationContext() {
return webApplicationContext;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
}
}
然后,您可以在JAX-WS端点类中实现自动装配。
@WebService
public class ServiceImpl implements ServicePortType {
@Autowired
private FooBean bean;
public ServiceImpl() {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
WebApplicationContext currentContext = WebApplicationContextLocator.getCurrentWebApplicationContext();
bpp.setBeanFactory(currentContext.getAutowireCapableBeanFactory());
bpp.processInjection(this);
}
// alternative constructor to facilitate unit testing.
protected ServiceImpl(ApplicationContext context) {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(new DefaultListableBeanFactory(context));
bpp.processInjection(this);
}
}
单元测试
在单元测试中,您可以注入当前的spring应用程序上下文,并使用它调用替代构造函数。
@Autowired
private ApplicationContext context;
private ServicePortType service;
@Before
public void setup() {
this.service = new ServiceImpl(this.context);
}
2020-11-16