Spring 3.1 M2:配置增强

工程 | Chris Beams | 2011年6月10日 | ...

正如 Juergen 在昨天的文章中提到的,正如我在之前的关于 3.1 M1 的文章我的 上一篇 文章中提到的那样,Spring 3.1 的主要主题之一是完成我们在 Spring 中基于代码配置的愿景。我们认为,现代企业级 Java 应用程序应该可以选择 Java 和 XML 作为其配置的一流选项。在这篇文章中,我们将看到 Spring 3.1 M2 如何使这成为现实。

请注意,尽管自 Spring 3.0 以来一直可以使用基于 Java 的配置,但在此版本中,它现在与多年来开发的许多基于 XML 的功能相当。我们认为结果非常吸引人,在某些情况下甚至比基于 XML 的配置具有明显的优势。简而言之:如果您在 3.0 中没有考虑它,那么您现在真的应该仔细研究一下。

Spring 的 XML 命名空间的代码等价物

如果您一直密切关注,您会记得我们在 3.1 M1 中引入了FeatureSpecification 类和@Feature 方法的概念。事实证明,我们决定在 3.1 M2 中用不同的机制替换它。为什么?因为尽管FeatureSpecification 类提供了一种方便的机制来配置 Spring 容器的功能,例如注解驱动的交易管理和组件扫描,但这带来了两个缺点:缺乏可扩展性和缺乏实现透明度。我们越想越意识到我们可以做得更好。虽然FeatureSpecification 类通过流畅的 API 紧密地镜像了 XML 命名空间,但新的解决方案采用了不同的形式——一种专门设计用来利用 Java 自身优势的形式。

简而言之,我们将新的机制称为“@Enable”注解。这些注解应用于@Configuration 类上的类型级别。让我们以@EnableTransactionManagement 为例。大多数用户都会熟悉以下 Spring XML 代码片段


<beans>
  <tx:annotation-driven/>
</beans>

这当然启用了 Spring 使用@Transactional 注解对事务管理的支持。现在让我们看看代码中的等效配置


@Configuration
@EnableTransactionManagement
public class AppConfig {
     // ...
}

很简单,对吧?当然还有更多内容要说,我鼓励大家查看我们在本版本中提供的@Enable 注解的Javadoc。您会发现它们包含大量上下文、示例和对重要相关类型的引用。它应该包含您入门所需的一切。当然,我们还将在 3.1 GA 之前更新参考文档,但我们跳过了 M2 的这一步,因为 Javadoc 已经得到了很多改进。

还要查看@Configuration 的Javadoc,它在 M2 中进行了大量修改,以展示与其他注解和机制(如新的Environment 抽象)的主要集成。

关于@EnableWebMvc 注解,这是一个基于 Java 的配置证明比 XML 命名空间替代方案具有真正优势的绝佳示例。Rossen 将在本系列的后续文章中详细介绍此主题,敬请关注。


Hibernate SessionFactory 构建器 API

Spring 对 Hibernate 的支持一直是该框架更受欢迎的功能之一,它始终通过 XML 进行配置。在 M2 中,我们引入了SessionFactoryBuilderAnnotationSessionFactoryBuilder API,这使得基于代码的 Hibernate SessionFactory 配置变得轻而易举。请查看


@Configuration
public class DataConfig {
     @Bean
     public SessionFactory sessionFactory() {
         return new AnnotationSessionFactoryBuilder()
             .setDataSource(dataSource())
             .setPackagesToScan("com.myco")
             .buildSessionFactory();
     }
}

请参阅 Javadoc 以了解更多示例和具体细节


无 XML 的 JPA 配置

使用 JPA 的 Spring 用户会熟悉我们的LocalContainerEntityManagerFactoryBean。我们添加了一个“packagesToScan”属性,允许您完全放弃 persistence.xml!顺便说一句,这与 Spring 的 Hibernate AnnotationSessionFactoryBean 上同名属性非常相似。这是一个示例


@Configuration
public class DataConfig {
     @Bean
     public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
         LocalContainerEntityManagerFactoryBean emf =
             new LocalContainerEntityManagerFactoryBean();
         emf.setDataSource(dataSource())
         emf.setPackagesToScan("com.myco")
         return emf;   
     }
}

放弃 web.xml

Servlet 3.0 引入了一些非常有趣的新功能,用于基于代码的 servlet 容器配置。本质上,ServletContext API 已得到增强,允许用户以基于类或基于实例的方式注册 servlet、过滤器和监听器。请查看

这意味着现在可以以编程方式注册面向 servlet 的组件,例如 Spring 的DispatcherServletContextLoaderListener,而不是通过 web.xml 以声明方式注册。

唯一缺少的是引导机制——在 servlet 容器生命周期的明确点执行这些注册的地方。幸运的是,Servlet 3.0 也解决了这个问题,使用了ServletContainerInitializer

ServletContainerInitializer 是一个低级 SPI,主要面向 Spring 等框架使用。我将细节留给 Javadoc(以下链接),但简而言之,Spring 3.1 M2 现在提供了一个非常方便的WebApplicationInitializer 接口,它与ServletContainerInitializer SPI 协同工作,允许您以编程方式引导 servlet 容器。这是一个快速示例


public class MyWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
      XmlWebApplicationContext appContext = new XmlWebApplicationContext()
      appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

      ServletRegistration.Dynamic dispatcher =
        container.addServlet("dispatcher", new DispatcherServlet(appContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");
    }

}

如您所见,DispatcherServlet 现在拥有一个接受WebApplicationContext 的构造函数。以下是 Javadoc

虽然我们在上面使用了XmlWebApplicationContext,但您当然也可以选择AnnotationConfigWebApplicationContext,并通过@Configuration 类完全引导。

spring-web 模块 JAR 存在于您的类路径中时,您的WebApplicationInitializer 实现将由 Spring 与ServletContainerInitializer 机制结合自动检测和处理。这意味着您可以根据需要准确地打包它们到您的应用程序中(再见,WEB-INF!)我们已经在 Glassfish 3.1 和 Tomcat 7.0.15 上成功测试了所有这些,所以现在是时候开始使用 Spring 3.1 和 Servlet 3.0 了。

有关完整的用法说明,请查看WebApplicationInitializer 本身的 Javadoc

有关从 web.xml 迁移到WebApplicationInitializer 的完整(且简洁)示例,请查看 Spring Greenhouse 参考应用程序的“servlet3”分支中的此提交


改进对外部化值的 支持

M1 引入了Environment 抽象和统一的PropertySource API。在 M2 中,我们的目标是使这些组件尽可能易于配置和使用。新的@PropertySource 注解允许您从@Configuration 类中为环境贡献属性源


 @Configuration
 @PropertySource("classpath:/com/myco/app.properties")
 public class AppConfig {
     @Autowired
     Environment env;

     @Bean
     public TestBean testBean() {
         TestBean testBean = new TestBean();
         testBean.setName(env.getProperty("testbean.name"));
         return testBean;
     }
 }

这与传统的PropertyPlaceholderConfigurer<context:property-placeholder>)方法不同。在这里,我们将属性源贡献给环境,将环境注入到我们的@Configuration 类中,然后使用环境的#getProperty 方法系列查找所需的属性。查看@PropertySourceEnvironment 的 Javadoc 以了解完整详细信息。


总结

如您所见,我们确实有一个主要的主题。从基于 Java 的替代方案到 Spring 的 XML 命名空间和FactoryBeans,再到消除 web.xml 和 persistence.xml 等非 Spring XML,我们现在可以自豪地说,Spring 的基于代码的配置在整个框架中都是一流的。唯一剩下的就是您的反馈!

正如 Juergen 提到的,如果您尚未开始,现在是尝试 3.1 的时候了。我们现在正在进入候选发布阶段,这是根据您的实际使用情况进行改进的最佳时机。请让我们知道您的使用情况如何!

哦,还有一件事……如果您还没有注意到,Spring 现在在 Twitter 上了!关注@springframework 以了解最新的发行版以及来自框架本身的 Spring 相关见解。希望在那里见到您,感谢您的阅读!

获取 Spring 电子报

通过 Spring 电子报保持联系

订阅

领先一步

VMware 提供培训和认证,以加快您的进度。

了解更多

获取支持

Tanzu Spring在一个简单的订阅中提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部