例子说明
之前我们通过xml来设置多应用上下文的spring,本例,我们将通过代码来进行设置。代码结构如图:
配置信息从代码中获取
上下文配置从代码中获取的设置
使用XML配置有下面的问题:
- 不能对XML配置进行debug
- 使用XML难以进行单元测试,都是整体测试
采用java代码配置可以解决上面的问题。spring启动时用AnnotationConfigWebApplicationContext来注册配置的类,而配置类需要标注@org.springframework.context.annotation.Configuration和有缺省的构造方法。配置类注册通过标注@Beaen的无参数方法注册bean。
根上下文配置
如果我们不是在要给xml文件中设置web app上下文(如root context),而是在代码中设置,相关的设置可修改为<!-- 使用AnnotationConfigWebApplicationContext,通过代码设置上下文的配置 -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<!-- AnnotationConfigWebApplicationContext通过某个类设置上下文的配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>cn.wei.flowingflying.chapter12.config.RootContextConfiguration</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
DispatcherServlet上下文配置
对于servlet上下文的配置,如果采用代码,相关设置可修改为:<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>cn.wei.flowingflying.chapter12.config.ServletContextConfiguration</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
上下文配置的实现:@Configuration
通过标记来替代xml文件
@Configuration中的标记 | xml中的内容 |
---|---|
@ComponentScan | <context:component-scan> |
@EnableAspectJAutoProxy | <aop:aspectj-autoproxy> |
@EnableAsync | 替代<task:*>的命名空间,并允许Spring的异步@Async方法执行 |
@EnableCaching | 替代<cache:*>的命名空间,并允许Spring的标记驱动缓存管理功能 |
@EnableLoadTimeWeaving | <context:load-time-weaver> |
@EnableMBeanExport | <context:mbean-export> |
@EnableScheduling | 替代<task:*>的命名空间,并激活有@Schedule标记的schedule方法执行。 |
@EnableSpringConfigured | <context:spring-configured> |
@EnableTransactionManagement | <tx:annotation-driven> |
@EnableWebMvc | <mvc:annotation-driven>,一般而言,需要扩展WebMvcConfigurerAdapter |
代码实现root上下文配置
/** @Configuration是@Component,因此可用扫描,可以通过@Autowired被注入。
- @Configurate可以实现任何的Aware接口,InitializingBean,DisposableBean,@PostConstruct和@PreDestroy。可以直接访问bean,或者由另一个@Configuration创建的bean;可以在依赖注入后初始化多个独立的bean。
- 注意被扫描的次数。 */
@Configuration
@ComponentScan(
basePackages = "cn.wei.flowingflying.chapter12.site",
excludeFilters = @ComponentScan.Filter(Controller.class)
)
public class RootContextConfiguration {
}
代码实现dispatcher servlet上下文配置
@Configuration
@EnableWebMvc
@ComponentScan(
basePackages = "cn.wei.flowingflying.chapter12.site",
useDefaultFilters = false,
includeFilters = @ComponentScan.Filter(Controller.class)
)
public class ServletContextConfiguration {
}
其他用途:读取配置文件
【properties文件】
可用于获取外部配置文件。使用@org.springframework.context.annotation.PropertySource人工获取,或者使用@org.springframework.beans.factory.annotation自动注入。
@Configuration
@PropertySource({
"classpath:com/wrox/config/settings.properties",
"file:config.properties"
})
public class ExampleConfiguration{
// 要获取property source的属性:
// - 可以注入org.springframework.core.env.Environment来人工获取,
// - 又或者使用@org.springframework.beans.factory.annotation.Value自动注入
@Inject Environment environment;
@Value("my.property.key") String myPropertyValue;
...
}
【XML文件】
有一些工具仍要求使用XML配置,如果spring的安全框架。使用@org.springframework.context.annotation.Import和@ImportResource
@Configuration
@Import({ DatabaseConfiguration.class, ClusterConfiguration.class })
@ImportResource("classpath:com/wrox/config/spring-security.xml")
public class ExampleConfiguration
...
代码启动spring
Spring提供org.springframework.web.SpringServletContainerInitializer来实现ServletContainerInitializer,而ServletContainerInitializer将在web app启动时调用,在任何listener之前。SpringServletContainerInitializer将扫描程序中有哪些实现org.springframework.web.WebApplicationInitializer接口,并调用其onStartup()。在此,我们可以编写代码来设置listener,servlet,filter,而不需要些xml配置,而我们也可以在此通过代码启动spring。
在代码中设置xml上下文配置文件的方式
public class Bootstrap implements WebApplicationInitializer{
@Override
public void onStartup(ServletContext container){
XmlWebApplicationContext rootContext = new XmlWebApplicationContext();
rootContext.setConfigLocation("/WEB-INF/rootContext.xml");
container.addListener(new ContextLoaderListener(rootContext));
XmlWebApplicationContext servletContext = new XmlWebApplicationContext();
servletContext.setConfigLocation("/WEB-INF/servletContext.xml");
ServletRegistration.Dynamic dispatcher = container.addServlet(
"springDispatcher", new DispatcherServlet(servletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
//default Servlet不需另外声明,已经具备
servletContext.getServletRegistration(“default”).addMapping(
"/resources/*", "*.css", "*.js", "*.png", "*.gif", "*.jpg");
}
}
WebApplicationInitializer接口实现Bootstrap
public class Bootstrap implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
//default Servlet不需另外声明,已经具备
container.getServletRegistration("default").addMapping("/resource/*");
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(cn.wei.flowingflying.chapter12.config.RootContextConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext servletContext = new AnnotationConfigWebApplicationContext();
servletContext.register(cn.wei.flowingflying.chapter12.config.ServletContextConfiguration.class);
ServletRegistration.Dynamic dispatcher = container.addServlet(
"springDispatcher", new DispatcherServlet(servletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
J2SE运行程序中启动spring
前面介绍的都是在J2EE容器中启动Spring,本文将实现如何在独立运行的J2SE应用中启动spring。public class Bootstrap{
public static void main(String... arguments){
// root context,其下带有两个web app 上下文
ClassPathXmlApplicationContext rootContext = new ClassPathXmlApplicationContext(
"com/yourcompany/yourproject/config/rootContext.xml");
//通过xml文件配置启动的servletContext
FileSystemXmlApplicationContext daemonContext = new FileSystemXmlApplicationContext(
new String[] {"file:/path/to/daemonContext.xml"}, rootContext );
//通过代码设置的servletContext
AnnotationConfigApplicationContext forkedProcessContext = new AnnotationConfigApplicationContext(
com.yourcompany.yourproject.config.ProcessContextConfiguration.class );
forkedProcessContext.setParent(rootContext);
rootContext.start();
rootContext.registerShutdownHook();
daemonContext.start();
daemonContext.registerShutdownHook();
forkedProcessContext.start();
forkedProcessContext.registerShutdownHook();
}
}