我在这里找到了一个100%基于代码的spring配置示例:
http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/web/WebApplicationInitializer.html
内容:
public class MyWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { // Create the 'root' Spring application context AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(AppConfig.class); // Manage the lifecycle of the root application context container.addListener(new ContextLoaderListener(rootContext)); // Create the dispatcher servlet's Spring application context AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); dispatcherContext.register(DispatcherConfig.class); // Register and map the dispatcher servlet ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }
在上面的示例中,他们从未注册配置类后调用过refresh()。但是API表示- 必须调用refresh()才能使上下文完全处理新类。所以我在每个注册语句之前添加了refresh()
rootContext.register(AppConfig.class); rootContext.refresh(); dispatcherContext.register(DispatcherConfig.class); dispatcherContext.refresh();
结果是:
SEVERE: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:702) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:699) at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1647) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:465) at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:415) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1487) at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:97) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1328) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1420) at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:848) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322) at sun.rmi.transport.Transport$1.run(Transport.java:177) at sun.rmi.transport.Transport$1.run(Transport.java:174) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:173) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.web.servlet.HandlerMapping org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping()] threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:592)
但是,如果我删除了refresh()(显然),它就可以正常工作(我使用的是Tomcat 8.0)最后,我不完全了解是否必须在这样的代码中使用refresh()。如果没有-我什么时候应该使用它?
在您的情况下,这仅对于ApplicationContext传递给来说很重要DispatcherServlet。该DispatcherServlet构造函数指出
ApplicationContext
DispatcherServlet
给定的Web应用程序上下文可能会或可能不会刷新。如果尚未刷新(推荐的方法),则会发生以下情况: 如果给定上下文还没有父级,则将根应用程序上下文设置为父级。 如果尚未为给定上下文分配一个ID,则会为其分配一个ID ServletContext 和ServletConfig对象将被委托给应用程序上下文 postProcessWebApplicationContext 将被称为 ApplicationContextInitializers通过“ contextInitializerClasses” init- param或setContextInitializers属性指定的任何内容都将应用。 refresh() 如果上下文实现,将被调用 ConfigurableApplicationContext 如果上下文已经刷新,则在用户已根据其特定需求执行(或未执行)这些操作的假设下,以上内容均不会发生。
给定的Web应用程序上下文可能会或可能不会刷新。如果尚未刷新(推荐的方法),则会发生以下情况:
ServletContext
ServletConfig
postProcessWebApplicationContext
ApplicationContextInitializers
refresh()
ConfigurableApplicationContext
如果上下文已经刷新,则在用户已根据其特定需求执行(或未执行)这些操作的假设下,以上内容均不会发生。
因此,对于DispatcherServlet,您必须执行以下操作
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); dispatcherContext.register(DispatcherConfig.class); // will take care of calling refresh() on the ApplicationContext ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
这对于DispatcherServlet配置是必需的,因为由于@EnableWebMvc(或等效<mvc:annotation- driven>)而生成的某些bean 需要Servlet容器提供的ServletContext和/或ServletConfig对象。
@EnableWebMvc
<mvc:annotation- driven>
根上下文不应具有此类依赖性,因此可以安全地执行此操作
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(AppConfig.class); rootContext.refresh();
请注意,您可以AnnotationConfigWebApplicationContext通过将@Configuration类作为参数传递给其构造函数来创建该对象。
AnnotationConfigWebApplicationContext
@Configuration