Pro Yearly is on sale from $80 to $50! »

Spring 3.1 Review (and 3.2 Preview)

Spring 3.1 Review (and 3.2 Preview)

As delivered at the Cloud Foundry Open Tour 2012 events in Kiev and Moscow.

21874091836ab7d3a769c1a89a0702f3?s=128

Chris Beams

April 24, 2012
Tweet

Transcript

  1. Spring 3.1 review (and 3.2 preview) Chris Beams SpringSource, VMware

  2. CHRIS BEAMS

  3. None
  4. None
  5. YOU

  6. YOU ... ?

  7. THIS PRESENTATION cbeams.github.com/spring-3.1-review

  8. Spring 3.1

  9. major themes first-class environment support code-based configuration new cache abstraction

    @MVC improvements third-party library and specification support
  10. Environment support

  11. Environment API

  12. Environment API injectable environment abstraction org.springframework.core.env.Environment

  13. Environment API captures two key concepts Property Sources Bean Definition

    Profiles
  14. PropertySource API abstraction for any source of key/value pairs .properties

    files system properties environment variables servlet context params JNDI
  15. PropertySource API Environment maintains a hierarchy of PropertySources

  16. StandardEnvironment includes by default PropertySources for: JVM system properties (-D

    flags) system environment variables suitable for use in standalone (i.e. non-web) apps
  17. StandardServletEnvironment includes by default PropertySources for: JVM system properties (-D

    flags) system environment variables servlet config and context params JNDI
  18. Putting the Environment to use All Spring ApplicationContext types now

    contain an Environment You can create and register your own Environment And/or customize with your own PropertySources Using ConfigurableEnvironment API or with @PropertySource annotation
  19. PropertySourcesPlaceholderConfigurer new in 3.1 supersedes PropertyPlaceholderConfigurer automatically resolves ${...} placeholders

    via the Environment used by default with <context:property-placeholder/>
  20. PropertySourcesPlaceholderConfigurer <beans ...> <context:property-placeholder location="classpath:com/company/db.properties"/> <bean id="dataSource" class="org.sfwk.jdbc.datasource.SimpleDriverDataSource"> <property name="driverClass"

    value="${db.driver}"/> <property name="url" value="${db.driver}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </bean> </beans>
  21. PropertySourcesPlaceholderConfigurer <beans ...> <context:property-placeholder location="classpath:com/company/db.properties"/> <bean id="dataSource" class="org.sfwk.jdbc.datasource.SimpleDriverDataSource"> <property name="driverClass"

    value="${db.driver}"/> <property name="url" value="${db.driver}"/> <property name="username" value="${db.username}"/> <property name="password" value="${db.password}"/> </bean> <!-- in 3.1, ${...} placeholders may be --> <!-- from 'db.properties' as well as all --> <!-- property sources registered with the --> </beans> <!-- Environment -->
  22. @Inject the Environment @Configuration public class DbConfig { @Bean public

    DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); return ds; } }
  23. @Inject the Environment @Configuration public class DbConfig { @Bean public

    DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); // configure and return the data source ... return ds; } }
  24. @Inject the Environment @Configuration public class DbConfig { @Bean public

    DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  25. @Inject the Environment @Configuration public class DbConfig { @Bean public

    DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); // where do these properties ds.setUsername(...); // come from? ds.setPassword(...); return ds; } }
  26. @Inject the Environment @Configuration public class DbConfig { @Bean public

    DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  27. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Bean

    public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  28. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  29. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; // injected from the enclosing // ApplicationContext @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  30. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(...); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  31. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(env.getPropertyAsClass("db.driver")); ds.setUrl(...); ds.setUsername(...); ds.setPassword(...); return ds; } }
  32. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(env.getPropertyAsClass("db.driver")); ds.setUrl(env.getProperty("db.url")); ds.setUsername(...); ds.setPassword(...); return ds; } }
  33. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(env.getPropertyAsClass("db.driver")); ds.setUrl(env.getProperty("db.url")); ds.setUsername(env.getProperty("db.username")); ds.setPassword(...); return ds; } }
  34. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(env.getPropertyAsClass("db.driver")); ds.setUrl(env.getProperty("db.url")); ds.setUsername(env.getProperty("db.username")); ds.setPassword(env.getProperty("db.password")); return ds; } }
  35. @Inject the Environment @PropertySource("classpath:/com/company/app/db.properties") @Configuration public class DbConfig { @Inject

    Environment env; @Bean public DataSource dataSource() { SimpleDriverDataSource ds = new SimpleDriverDataSource(); ds.setDriverClass(env.getPropertyAsClass("db.driver")); ds.setUrl(env.getProperty("db.url")); ds.setUsername(env.getProperty("db.username")); ds.setPassword(env.getProperty("db.password")); return ds; // property values may be resolved from } // 'db.properties' or any other PropertySource } // registered with the Environment
  36. bean definition profiles

  37. bean definition profiles a logical group of bean definitions registered

    only if the profile is active
  38. abc-config.xml <beans> <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean id="c"

    class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); // ... }
  39. abc-config.xml <beans profile="dev"> <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean

    id="c" class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); // ... }
  40. abc-config.xml <beans profile="dev"> <!-- only register if "dev" active -->

    <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean id="c" class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); // ... }
  41. abc-config.xml <beans profile="dev"> <!-- only register if "dev" active -->

    <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean id="c" class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); // oops! "dev" profile not active, // so bean "a" is not found }
  42. abc-config.xml <beans profile="dev"> <!-- only register if "dev" active -->

    <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean id="c" class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); }
  43. abc-config.xml <beans profile="dev"> <!-- only register if "dev" active -->

    <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean id="c" class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.getEnvironment().setActiveProfiles("dev"); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); }
  44. abc-config.xml <beans profile="dev"> <!-- only register if "dev" active -->

    <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean id="c" class="com.company.C"/> </beans> Main.java public static void main(String... args) { GenericXmlApplicationContext ctx = new GXAC(); ctx.getEnvironment().setActiveProfiles("dev"); ctx.load("classpath:com/company/*-config.xml"); ctx.refresh(); ctx.getBean("a"); // "dev" profile is active, so // bean "a" is available }
  45. profile use cases differing configurations across dev/test/prod lifecycle customer A

    vs. customer B deployments portability across traditional and cloud environments ...
  46. dev-datasource-config.xml <beans profile="dev"> <bean id="dataSource" class="org.opensource.InMemoryDB"> <property name="driverClass" value="..."/> <property

    name="url" value="..."/> <property name="username" value="..."/> <property name="password" value="..."/> </bean> </beans>
  47. dev-datasource-config.xml <beans profile="dev"> <bean id="dataSource" class="org.opensource.InMemoryDB"> <property name="driverClass" value="..."/> <property

    name="url" value="..."/> <property name="username" value="..."/> <property name="password" value="..."/> </bean> </beans> prod-datasource-config.xml <beans profile="prod"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myds"/> </beans>
  48. nested <beans/>

  49. datasource-config.xml <beans> <beans profile="dev"> </beans> <beans profile="prod"> </beans> </beans>

  50. datasource-config.xml <beans> <beans profile="dev"> <bean id="dataSource" class="org.opensource.InMemoryDB"> <property name="driverClass" value="..."/>

    <property name="url" value="..."/> <property name="username" value="..."/> <property name="password" value="..."/> </bean> </beans> <beans profile="prod"> </beans> </beans>
  51. datasource-config.xml <beans> <beans profile="dev"> <bean id="dataSource" class="org.opensource.InMemoryDB"> <property name="driverClass" value="..."/>

    <property name="url" value="..."/> <property name="username" value="..."/> <property name="password" value="..."/> </bean> </beans> <beans profile="prod"> <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/myds"/> </beans> </beans>
  52. profile activation

  53. programmatic GenericApplicationContext ctx = ...; ctx.getEnvironment().setActiveProfiles("dev"); ctx.refresh(); // ...

  54. declarative: JVM system props spring.profiles.active

  55. declarative: JVM system props -Dspring.profiles.active=p1,p2,p3

  56. <web-app> <servlet> <servlet-name>main</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>spring.profiles.active</param-name> <param-value>p1,p2,p3</param-value> </init-param>

    <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/dispatcher-config.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- ... --> <web-app>
  57. <web-app> <servlet> <init-param> <param-name>spring.profiles.active</param-name> <param-value>p1,p2,p3</param-value> </init-param> </servlet> <!-- ... -->

    <web-app>
  58. Code-based configuration

  59. Goal: 100% XML-free application configuration

  60. @Configuration, completed Spring 3.0 introduced the @Configuration class

  61. app-config.xml <beans> <bean id="foo" class="com.company.Foo"> <property name="bar" ref="bar"/> </bean> <bean

    id="bar" class="com.company.Bar"/> </beans> ... new GenericXmlApplicationContext("app-config.xml");
  62. AppConfig.java @Configuration public class AppConfig { @Bean public Foo foo()

    { Foo foo = new Foo(); foo.setBar(bar()); return foo; } @Bean public Bar bar() { return new Bar(); } } ... new AnnotationConfigApplicationContext(AppConfig.class);
  63. @Configuration in Spring 3.0 works well, but incomplete e.g. no

    equivalent to Spring XML namespaces
  64. XML namespaces <beans> </beans>

  65. XML namespaces <beans> <!-- scan for all @Component-annotated classes -->

    <context:component-scan base-package="com.company"/> </beans>
  66. XML namespaces <beans> <!-- scan for all @Component-annotated classes -->

    <context:component-scan base-package="com.company"/> <!-- handle any @Transactional annotations --> <tx:annotation-driven/> </beans>
  67. XML namespaces <beans> <!-- scan for all @Component-annotated classes -->

    <context:component-scan base-package="com.company"/> <!-- handle any @Transactional annotations --> <tx:annotation-driven/> <!-- handle any @Scheduled annotations --> <task:annotation-driven/> </beans>
  68. XML namespaces <beans> <!-- scan for all @Component-annotated classes -->

    <context:component-scan base-package="com.company"/> <!-- handle any @Transactional annotations --> <tx:annotation-driven/> <!-- handle any @Scheduled annotations --> <task:annotation-driven/> <!-- ... --> </beans>
  69. @Enable* annotations

  70. @Enable* and @ComponentScan provide the missing equivalent to XML namespaces

  71. <beans> <context:component-scan base-package="com.company"/> <tx:annotation-driven/> <task:annotation-driven/> <!-- ... --> </beans>

  72. @Configuration @ComponentScan("com.company") @EnableTransactionManagement @EnableScheduling public class AppConfig { // ...

    }
  73. @Configuration @ComponentScan("com.company") // ~= context:component-scan @EnableTransactionManagement @EnableScheduling public class AppConfig

    { // ... }
  74. @Configuration @ComponentScan("com.company") @EnableTransactionManagement // ~= tx:annotation-driven @EnableScheduling public class AppConfig

    { // ... }
  75. @Configuration @ComponentScan("com.company") @EnableTransactionManagement @EnableScheduling // ~= task:annotation-driven public class AppConfig

    { // ... }
  76. @ComponentScan @EnableAspectJAutoProxy @EnableAsync @EnableCaching @EnableLoadTimeWeaving @EnableSpringConfigured @EnableTransactionManagement @EnableWebMvc

  77. design goals for @Enable* annotations transparency flexibility extensibility

  78. @Profile annotation equivalent to <beans profile="..."/>

  79. abc-config.xml <beans profile="dev"> <bean id="a" class="com.company.A"/> <bean id="b" class="com.company.B"/> <bean

    id="c" class="com.company.C"/> </beans>
  80. AbcConfig.xml @Configuration public class AbcConfig { @Bean A a() {

    return new A(); } @Bean B b() { return new B(); } @Bean C c() { return new C(); } }
  81. AbcConfig.xml @Configuration @Profile("dev") public class AbcConfig { @Bean A a()

    { return new A(); } @Bean B b() { return new B(); } @Bean C c() { return new C(); } }
  82. @Configuration support in TestContext framework

  83. TestContext framework @ContextConfiguration and friends introduced in Spring 2.5 big

    help with integration tests until 3.1, worked only with XML
  84. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(locations="app-config.xml") public class IntegrationTest { @Autowired MyService myService; @Test

    public void testServiceMethods() { // ... } }
  85. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(locations="app-config.xml") public class IntegrationTest { @Autowired MyService myService; //

    inject a <bean> @Test public void testServiceMethods() { // ... } }
  86. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(locations="app-config.xml") public class IntegrationTest { }

  87. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(classes=AppConfig.class) public class IntegrationTest { }

  88. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(classes=AppConfig.class) // new in 3.1 public class IntegrationTest {

    }
  89. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(classes=AppConfig.class) public class IntegrationTest { @Autowired MyService myService; @Test

    public void testServiceMethods() { // ... } }
  90. @RunWith(SpringJunit4ClassRunner.class) @ContextConfiguration(classes=AppConfig.class) public class IntegrationTest { @Autowired MyService myService; //

    inject a @Bean @Test public void testServiceMethods() { // ... } }
  91. XML-free servlet container configuration

  92. WebApplicationInitializer Spring 3.1 introduces WebApplicationInitializer API builds on Servlet 3.0

    ServletContainerInitializer auto-detected on servlet container startup eliminates need for web.xml entirely
  93. <web-app> <servlet> <servlet-name>main</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/dispatcher-config.xml

    </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>main</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <web-app>
  94. WebApplicationInitializer equivalent public class MyWAI implements WebApplicationInitializer { @Override public

    void onStartup(ServletContext servletContext) { XmlWebApplicationContext appContext = new XmlWebApplicationContext() appContext.setConfigLocation( "/WEB-INF/spring/dispatcher-config.xml"); Dynamic servlet = servletContext.addServlet( "main", new DispatcherServlet(appContext)); servlet.addMapping("/"); servlet.setLoadOnStartup(1); } }
  95. even better - 100% XML-free public class MyWAI implements WebApplicationInitializer

    { @Override public void onStartup(ServletContext servletContext) { AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext() appContext.register(AppConfig.class); Dynamic servlet = servletContext.addServlet( "main", new DispatcherServlet(ctx)); servlet.addMapping("/"); servlet.setLoadOnStartup(1); } }
  96. XML-free JPA

  97. persistence.xml <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="..." xsi:schemaLocation="..." version="2.0"> <persistence-unit name="sample"> <jta-data-source>java:/DefaultDS</jta-data-source> <properties>

    <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> </properties> </persistence-unit> </persistence>
  98. @Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();

    emf.setDataSource(dataSource()); emf.setPersistenceXmlLocation( "classpath:META-INF/persistence.xml"); return emf; }
  99. @Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();

    emf.setDataSource(dataSource()); emf.setPersistenceXmlLocation( "classpath:META-INF/persistence.xml"); // no more! return emf; }
  100. @Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();

    emf.setDataSource(dataSource()); emf.setPackagesToScan("com.biz.app"); return emf; }
  101. @Bean public LocalContainerEntityManagerFactoryBean emf() { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();

    emf.setDataSource(dataSource()); // scan classpath for JPA @Entity types emf.setPackagesToScan("com.biz.app"); return emf; }
  102. XML-free Hibernate configuration

  103. Hibernate 4 support Spring 3.1 builds against Hib 4.1 new

    orm.hibernate4 packaging
  104. familiar? <bean id="sessionFactory" class="org.sfwk.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="mappingResources"> <list>

    <value>Person.hbm.xml</value> <value>Account.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.HSQLDialect </value> </property> </bean>
  105. or even <bean id="sessionFactory" class="org.sfwk.orm.hib3.AnnotationSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="annotatedClasses">

    <list> <value>com.foo.Person</value> <value>com.foo.Account</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.HSQLDialect </value> </property> </bean>
  106. We can do better than that.

  107. @Bean public SessionFactory sessionFactory() { return new LocalSessionFactoryBuilder(dataSource()) .addAnnotatedClasses(Person.class, Account.class)

    .buildSessionFactory(); }
  108. LocalSessionFactoryBuilder extends Hibernate's own Configuration class only in the new

    orm.hibernate4 package
  109. also...

  110. standalone Hibernate exception translator @Bean public SessionFactory sessionFactory() { return

    new LocalSessionFactoryBuilder(dataSource()) .addAnnotatedClasses(Person.class, Account.class) .buildSessionFactory(); } @Bean public PersistenceExceptionTranslator exTranslator() { return new HibernateExceptionTranslator(); }
  111. application-context.xml persistence.xml web.xml

  112. comprehensive code-based config Spring 3.0 began the work Spring 3.1

    completes it
  113. "but what about XML?" don't worry... Spring XML will always

    remain first-class code config is there for those that want it
  114. New cache abstraction

  115. declarative caching for Spring- managed beans minimal impact on code

    plug in various cache providers
  116. key annotations @Cacheable @CacheEvict

  117. @Cacheable("books") public Book findBook(ISBN isbn) { return this.bookRepository.findBook(isbn); } @CacheEvict(value="books",

    allEntries=true) public void loadBooks(InputStream batch) { // ... }
  118. Cache and CacheManager SPI in new org.springframework.cache package

  119. enable caching support with new <cache:*> XML namespace or new

    @EnableCaching annotation
  120. <cache:*> namespace <cache:annotation-driven/> <bean id="cacheManager" class="org.sfwk.cache.support.SimpleCacheManager"/> <property name="caches"> <bean class="org.sfwk...ConcurrentMapCacheFactoryBean">

    <property name="name" value="books"/> </bean> </property> </bean>
  121. @EnableCaching annotation @Configuration @EnableCaching class AppConfig { @Bean public CacheManager

    cacheManager() { ConcurrentMapCacheManager mgr = new ConcurrentMapCacheManager(); mgr.setCacheNames(Collections.singleton("books")); return mgr; } }
  122. out-of-the-box implementations for Ehcache Concurrent map (in-memory) any provider can

    be plugged in GemFire, Coherence, etc. JCache support in Spring 3.2
  123. Improvements in @MVC

  124. Improvements in @MVC new HandlerMethod-based approach flash attribute support @Validated

    annotation supporting JSR-303 groups @Valid support on @RequestBody method args HDIV security framework integration
  125. Improvements in @MVC complete support for code config with @EnableWebMvc

    even more flexibility important improvements for RESTful services too much to cover here! see @rstoyanchev's spring-mvc-3.1-update
  126. Third-party libs and spec support

  127. Servlet 3.0 as discussed earlier primarily focused on config Spring

    3.2 will focus on async use cases
  128. Hibernate 4.x support currently up to date with 4.1.0 now

    in dedicated orm.hibernate4 package includes LocalSessionFactoryBuilder discussed earlier
  129. Quartz 2.0/2.1 enhancements to JobFactoryBean et al. see SPR-8889

  130. JDBC 4.1 enhancements to Spring's ResultSetExtractor in support of JDBC

    4.1's RowSetProvider API
  131. JDK 7 fork/join pool support new ForkJoinPoolFactoryBean

  132. bonus

  133. c: namespace equivalent to p: namespace (around since Spring 2.0)

  134. a typical component package com.company; public class Baz { private

    final Foo foo; private Bar bar; public Baz(Foo foo) { this.foo = foo; } public setBar(Bar bar) { this.bar = bar; } }
  135. and it's typical config <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...> <bean id="foo"

    class="com.company.Foo"> <bean id="bar" class="com.company.Bar"> <bean name="baz" class="com.company.Baz"> <constructor-arg ref="foo"/> <property name="bar" ref="bar"/> </bean> </beans>
  136. ... with p: namespace <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" ...> <bean

    id="foo" class="com.company.Foo"> <bean id="bar" class="com.company.Bar"> <bean name="baz" class="com.company.Baz" p:bar-ref="bar"> <constructor-arg ref="foo"/> </bean> </beans>
  137. ... with c: namespace <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" ...>

    <bean id="foo" class="com.company.Foo"> <bean id="bar" class="com.company.Bar"> <bean name="baz" class="com.company.Baz" p:bar-ref="bar" c:foo-ref="foo"/> </beans>
  138. Spring 3.2

  139. Major Themes Project infrastructure improvements Asynchronous request processing Ease of

    use Third-party library and specification support
  140. project infrastructure improvements

  141. a.k.a. "Spring Cleaning"

  142. Spring Cleaning Move to GitHub New build system New SpringSource

    repository New springsource.org site
  143. All sources now on GitHub

  144. None
  145. None
  146. All sources now on GitHub and not just spring-framework

  147. spring-framework spring-batch spring-integration spring-security spring-webflow spring-data-* every active Spring project

    has made the move
  148. new build system

  149. new build system from Ant/Ivy to Gradle used to take

    a whole blog post to explain now just one command
  150. checkout, build, test $ git clone git@github.com/SpringSource/spring-framework.git $ cd spring-framework

    $ ./gradlew build ... BUILD SUCCESSFUL
  151. install jars to local m2 cache $ ./gradlew install ...

    BUILD SUCCESSFUL
  152. None
  153. STS and Gradle STS Gradle tooling tutorial

  154. new build system great for core developers but also great

    for the community!
  155. simple build + GitHub pull requests = contributions welcome

  156. contributions welcome contributor guidelines complete instructions for building from source

    current list of pull requests
  157. unified artifact management

  158. http://repo.springsource.org

  159. None
  160. None
  161. repo.springsource.org single location for all Spring artifacts and dependencies GA

    releases also published to Maven Central
  162. repo.springsource.org see downloading Spring artifacts and the SpringSource repository FAQ

  163. New http://springsource.org

  164. None
  165. None
  166. Asynchronous request processing

  167. Asynchronous request processing support in @MVC for Servlet 3.0/3.1 async

    may also incorporate Web Sockets stay tuned to blog.springsource.com feedback please!
  168. Asynchronous request processing sneak preview: spring-mvc-chat follow SPR-8517

  169. Third-party libs and spec support

  170. Third-party libs and spec support JPA 2.1 (SPR-8194) JSF 2.2

    (SPR-8104) JMS 2.0 (SPR-8197) JCache 1.0 (SPR-8774) Bean Validation 1.1 (SPR-8199)
  171. Ease of use

  172. Ease of use migrate away from CGLIB (SPR-8190) logging improvements

    (SPR-8122) error-reporting improvements (SPR-8204)
  173. Roadmap 3.1.1 is out, 3.1.2 on the way 3.2 M1

    just around the corner 3.2 GA around year-end 2012
  174. Thanks! Questions? cbeams.github.com/spring-3.1-review twitter.com/cbeams