| z, ? | toggle help (this) |
| space, → | next slide |
| shift-space, ← | previous slide |
| d | toggle debug mode |
| ## <ret> | go to slide # |
| c, t | table of contents (vi) |
| f | toggle footer |
| r | reload slides |
| n | toggle notes |
| p | run preshow |
<beans/><beans>
</beans><beans>
<bean id="foo" class="com.foo.Foo"/>
</beans><beans>
<bean id="foo" class="com.foo.Foo"/>
<bean id="bar" class="com.foo.Bar">
<property name="foo" ref="foo"/>
</bean>
</beans><beans>
<bean id="foo" class="com.foo.Foo"/>
<bean id="bar" class="com.foo.Bar">
<property name="foo" ref="foo"/>
</bean>
<bean .../>
</beans><beans>
<bean id="foo" class="com.foo.Foo"/>
<bean id="bar" class="com.foo.Bar">
<property name="foo" ref="foo"/>
</bean>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
</beans><beans>
<bean id="foo" class="com.foo.Foo"/>
<bean id="bar" class="com.foo.Bar">
<property name="foo" ref="foo"/>
</bean>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
</beans><beans>
<bean id="foo" class="com.foo.Foo"/>
<bean id="bar" class="com.foo.Bar">
<property name="foo" ref="foo"/>
</bean>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<bean .../>
<import resource="more-beans.xml"/>
</beans><namespace:*/><tx:annotation-driven/>
<aop:aspectj-autoproxy/>
<jee:jndi-lookup/>
<util:list/>@Autowired@Component<context:component-scan/>@Controllers@Qualifier)package com.win;
@Component
public class TehAwesome {
@Autowired
public void setStuff(Stuff stuff) { ... }
}
package com.win;
@Component
public class TehAwesome {
@Autowired
public void setStuff(Stuff stuff) { ... }
}
<context:component-scan base-package="com.win"/>@Configuration@Bean
@Configuration
public class AppConfig {
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
return quoteService;
}
}// @Configuration classes =~ <beans/> documents
@Configuration
public class AppConfig {
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
return quoteService;
}
}
@Configuration
public class AppConfig {
// @Bean methods ~= <bean/> elements
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
return quoteService;
}
}
@Configuration
public class AppConfig {
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = // instantiate
return quoteService;
}
}
@Configuration
public class AppConfig {
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
// configure
return quoteService;
}
}
@Configuration
public class AppConfig {
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
return quoteService; // object managed by Spring
}
}@Import(OtherConfig.class) // =~ <import/>
@Configuration
public class AppConfig {
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
return quoteService;
}
}@Import(OtherConfig.class)
@Configuration
public class AppConfig {
@Autowired QuoteSource quoteSource; // from OtherConfig
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
return quoteService;
}
}@Import(OtherConfig.class)
@Configuration
public class AppConfig {
@Autowired QuoteSource quoteSource;
@Bean
public QuoteService quoteService() {
RealTimeQuoteService quoteService = ...;
quoteService.setQuoteSource(quoteSource); // inject
return quoteService;
}
}
public class Main {
public static void main(String... args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
QuoteService quoteService =
ctx.getBean(QuoteService.class);
System.out.println(quoteService.currentValue("AAPL"));
}
}
public class Main {
public static void main(String... args) {
// bootstrap the Spring container
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
QuoteService quoteService =
ctx.getBean(QuoteService.class);
System.out.println(quoteService.currentValue("AAPL"));
}
}
public class Main {
public static void main(String... args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
// retrieve the bean we want to use in type-safe fashion
QuoteService quoteService =
ctx.getBean(QuoteService.class);
System.out.println(quoteService.currentValue("AAPL"));
}
}
public class Main {
public static void main(String... args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(AppConfig.class);
QuoteService quoteService =
ctx.getBean(QuoteService.class);
// use the bean however desired
System.out.println(quoteService.currentValue("AAPL"));
}
}<namespace:*/>Environment APIPropertySource API<beans profile="dev"/>@Profile("dev")<beans/>c: namespace@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("app-context.xml")
public class MyTest {
@Autowired MyBean bean;
@Test
public void testXyz() {
}
}@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from app-context.xml
@ContextConfiguration("app-context.xml")
public class MyTest {
@Autowired MyBean bean;
@Test
public void testXyz() {
}
}@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("app-context.xml")
public class MyTest {
@Autowired MyBean bean; // injected from app-context.xml
@Test
public void testXyz() {
}
}@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("app-context.xml")
public class MyTest {
@Autowired MyBean bean;
@Test
public void testXyz() {
// assertions against bean
}
}@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)
public class MyTest {
@Autowired MyBean bean;
@Test
public void testXyz() {
// assertions against bean
}
}@RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from AppConfig
@ContextConfiguration(classes=AppConfig.class)
public class MyTest {
@Autowired MyBean bean;
@Test
public void testXyz() {
// assertions against bean
}
}@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=AppConfig.class)
public class MyTest {
@Autowired MyBean bean; // injected from AppConfig
@Test
public void testXyz() {
// assertions against bean
}
}@Configuration, @Profile@Configuration classes blog post@Enable*@Enable*(and friends)
@EnableTransactionManagement
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving
@EnableScheduling
@EnableAsync
@EnableWebMvc
@ComponentScanpackage com.win;
@Component
public class TehAwesome {
@Autowired
public void setStuff(Stuff stuff) { ... }
}
package com.win;
@Component
public class TehAwesome {
@Autowired
public void setStuff(Stuff stuff) { ... }
}
<context:component-scan base-package="com.win"/>package com.win;
@Component
public class TehAwesome {
@Autowired
public void setStuff(Stuff stuff) { ... }
}
@ComponentScan("com.win")package com.win;
@Repository
public class WidgetRepo {
@Transactional
public void add(Widget widget) { ... }
}
package com.win;
@Repository
public class WidgetRepo {
@Transactional
public void add(Widget widget) { ... }
}
<tx:annotation-driven/>package com.win;
@Repository
public class WidgetRepo {
@Transactional
public void add(Widget widget) { ... }
}
@EnableTransactionManagement@EnableScheduling@EnableSchedulingpackage com.startup;
public class ChatterBox {
public void saySomething() {
System.out.println(randomWord());
}
}package com.startup;
public class ChatterBox {
@Scheduled(fixedRate=1000)
public void saySomething() {
System.out.println(randomWord());
}
}package com.startup;
public class ChatterBox {
// (@Scheduled has been
@Scheduled(fixedRate=1000) // around since Spring 3.0)
public void saySomething() {
System.out.println(randomWord());
}
}package com.startup;
public class ChatterBox {
// "hey Spring, call this
@Scheduled(fixedRate=1000) // method every second"
public void saySomething() {
System.out.println(randomWord());
}
}package com.startup.config;
@Configuration
public class Config {
@Bean
public ChatterBox chatterBox() {
return new ChatterBox();
}
}package com.startup.config;
@Configuration
@EnableScheduling
public class Config {
@Bean
public ChatterBox chatterBox() {
return new ChatterBox();
}
}package com.startup.config;
@Configuration
@EnableScheduling // look for and process @Scheduled
public class Config {
@Bean
public ChatterBox chatterBox() {
return new ChatterBox();
}
}package com.startup.config;
@Configuration
@EnableScheduling
public class Config {
@Bean
public ChatterBox chatterBox() {
return new ChatterBox(); // saySomething() method
} // called once per second
}package com.startup.config;
@Configuration
@EnableScheduling // ok, so what does this do?
public class Config {
@Bean
public ChatterBox chatterBox() {
return new ChatterBox();
}
}package org.springframework.scheduling.annotation;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}package org.springframework.scheduling.annotation;
@Import(SchedulingConfiguration.class) // this is the key =>
public @interface EnableScheduling {
}package org.springframework.scheduling.annotation;
@Configuration
public class SchedulingConfiguration {
@Bean(name=SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor sabpp() {
return new ScheduledAnnotationBeanPostProcessor();
}
}package org.springframework.scheduling.annotation;
@Configuration
public class SchedulingConfiguration {
// it's just registering the @Scheduled bean
// post processor on your behalf
public ScheduledAnnotationBeanPostProcessor sabpp() {
return new ScheduledAnnotationBeanPostProcessor();
}
}@Import now supported at annotation level@Enable* is just a naming convention@Configuration classes shipped out of the box@Configuration all the way down"@EnableWebMvc
throw to Rossen here
<name>-servlet.xmlDispatcherServlet.propertiesHandlerMapping, HandlerAdapter .. and other types to instantiate by default
<mvc:annotation-driven />
BeanDefinitionParserBeanPostProcessor works .. not obvious!Many copy+paste AnnotationMethodHandlerAdapter config not seeing it overlaps with the config from <mvc:annotation-driven />
// Equivalent to <mvc:annotation:driven/>
@EnableWebMvc
@Configuration
public class WebConfig {
}
// Equivalent to <mvc:annotation:driven/>
@EnableWebMvc // <-- What's behind ?
@Configuration
public class WebConfig {
}@EnableWebMvc
@Retention(RetentionPolicy.RUNTIME)
@Import(DelegatingWebMvcConfiguration.class)
@Target(ElementType.TYPE)
public @interface EnableWebMvc {
}@EnableWebMvc
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}web.xml
<!-- 1. Change ApplicationContext type -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.
AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<!-- 2. Point to package with @Configuration classes -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
org.example.somepackage
</param-value>
</context-param>WebMvcConfigurerWebMvcConfigurerAdapter
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
protected void addFormatters(FormatterRegistry registry) {
// ...
}
@Override
public void addInterceptors(InterceptorRegistry reg){
// Equivalent to <mvc:interceptors>
}
@Override
public void addViewControllers(ViewControllerRegistry reg) {
// Equivalent to <mvc:view-controller>
}
}WebMvcConfigurer targets the 80%Once again the ease-of-use vs. control issue exceptin this time not a dilemma
WebMvcConfigurationSupport@EnableWebMvc@Bean methodsEasier to read is relative to reading BeanDefinitionParser code with the MVC namespace
@EnableWebMvcWebMvcConfigurationSupportWebMvcConfigurer@Bean methods!
@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry reg){
// Equivalent to <mvc:interceptors>
}
@Override
@Bean
public RequestMappingHandlerAdapter
requestMappingHandlerAdapter() {
// Create or let "super" create and customize
// RequestMappingHandlerAdapter ...
}
}@Enable*
for dependency injection
for enabling features of the Spring container
for Hibernate integration, too
<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><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><bean id="sessionFactory"
class="org.sfwk.orm.hib3.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="annotatedClasses">
<list>
<value>com.foo.Person</value> <!-- again the irony -->
<value>com.foo.Account</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>@Bean
public SessionFactory sessionFactory() {
return new LocalSessionFactoryBuilder(dataSource())
.addAnnotatedClasses(Person.class, Account.class)
.buildSessionFactory();
}@Bean
public SessionFactory sessionFactory() {
return new LocalSessionFactoryBuilder(dataSource())
.addAnnotatedClasses(Person.class, Account.class)
.buildSessionFactory();
}
@Bean
public PersistenceExceptionTranslator exTranslator() {
return new HibernateExceptionTranslator();
}and not just Spring 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>@Bean
public LocalContainerEntityManagerFactoryBean emf() {
LocalContainerEntityManagerFactoryBean emf =
new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
emf.setPersistenceXmlLocation(
"classpath:META-INF/persistence.xml");
return emf;
}@Bean
public LocalContainerEntityManagerFactoryBean emf() {
LocalContainerEntityManagerFactoryBean emf =
new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
emf.setPersistenceXmlLocation(
"classpath:META-INF/persistence.xml"); // no more!
return emf;
}@Bean
public LocalContainerEntityManagerFactoryBean emf() {
LocalContainerEntityManagerFactoryBean emf =
new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
emf.setPackagesToScan("com.win.entity");
return emf;
}@Bean
public LocalContainerEntityManagerFactoryBean emf() {
LocalContainerEntityManagerFactoryBean emf =
new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
// scan classpath for JPA @Entity types
emf.setPackagesToScan("com.win.entity");
return emf;
}and not just Spring XML
<web-app>
<servlet>
<servlet-name>dispatcher</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>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<web-app>public class WebInit implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext ctx =
new XmlWebApplicationContext()
ctx.setConfigLocation(
"/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic dispatcher =
container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}public class WebInit implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext ctx =
new AnnotationConfigWebApplicationContext()
ctx.register(DispatcherConfig.class);
ServletRegistration.Dynamic dispatcher =
container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}

if you want it*
@cbeams@rstoya05@springframework