Transcript
Page 1: Modern Component Design with Spring

© 2013 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Modern Component Design with Spring

Juergen Hoeller

Page 2: Modern Component Design with Spring

Overview: Spring Component Model Themes● Powerful annotated component model● Custom annotations through composition● Configuration classes and factory methods● Spring Expression Language● Flexible MVC/REST controller style● Declarative validation and formatting● Declarative scheduling and caching

Page 3: Modern Component Design with Spring

Bootstrapping Your Annotated Components● Typical: XML bean definition file

– <context:component-scan base-package=”com.myapp”/>– @Component / @Repository / @Service / @Configuration stereotype– compare: JPA persistence.xml with @Entity classes

● Alternative: AnnotationConfigApplicationContext– scan(basePackage)– register(componentClass)– register(configurationClass)

Page 4: Modern Component Design with Spring

A Typical Annotated Component@Servicepublic class MyBookAdminService implements BookAdminService { @Autowired public MyBookAdminService(AccountRepository ar) { ... }

@Transactional public BookUpdate updateBook(Addendum addendum) { ... }}

Page 5: Modern Component Design with Spring

A More Specific Annotated Component@Service@Scope("session")@Primarypublic class MyBookAdminService implements BookAdminService { @Autowired @Qualifier("production") public MyBookAdminService(@Lazy AccountRepository ar) { ... }

@Transactional(readOnly=false, timeout=10) public BookUpdate updateBook(Addendum addendum) { ... }}

Page 6: Modern Component Design with Spring

Composable Stereotype Model@Service@Scope("session")@Primary@Transactional(rollbackFor=Exception.class)@Retention(RetentionPolicy.RUNTIME)public @interface MyService {}

@MyServicepublic class MyBookAdminService { ...}

Page 7: Modern Component Design with Spring

Custom Scoping Annotations@Scope(value="session", proxyMode=ScopedProxyMode.INTERFACES)@Retention(RetentionPolicy.RUNTIME)public @interface MySessionScoped {}

@Scope(value="session")@Retention(RetentionPolicy.RUNTIME)public @interface MySessionScoped { ScopedProxyMode proxyMode() default ScopedProxyMode.NO;}

Page 8: Modern Component Design with Spring

Custom Transaction Annotations@Transactional(readOnly=false, timeout=10)@Retention(RetentionPolicy.RUNTIME)public @interface MyTransactional {}

@Transactional(rollbackFor=Exception.class)@Retention(RetentionPolicy.RUNTIME)public @interface MyTransactional { boolean readOnly();}

Page 9: Modern Component Design with Spring

Annotated Factory Methods@Bean@Scope("session")@Primarypublic BookAdminService bookAdminService() { MyBookAdminService service = new MyBookAdminService(); service.setDataSource(…); return service;}

@Beanpublic BookAdminService bookAdminService() { return MyServiceFactory.createBookAdminService();}

Page 10: Modern Component Design with Spring

Configuration Classes@Configurationpublic class MyBookAdminConfig { @Bean public BookAdminService myBookAdminService() { MyBookAdminService service = new MyBookAdminService(); service.setDataSource(bookAdminDataSource()); return service; }

@Bean public DataSource bookAdminDataSource() { ... }}

Page 11: Modern Component Design with Spring

Configuration with Profile and Enable*@Configuration@Profile("standalone")@EnableTransactionManagementpublic class MyBookAdminConfig { @Bean public BookAdminService myBookAdminService() { MyBookAdminService service = new MyBookAdminService(); service.setDataSource(bookAdminDataSource()); return service; }

...}

Page 12: Modern Component Design with Spring

EL in Component Annotations@Repositorypublic class BookTestDatabase { @Value("#{systemProperties.databaseName}") public void setDatabaseName(String dbName) { ... }

@Value("#{strategyBean.databaseKeyGenerator}") public void setKeyGenerator(KeyGenerator kg) { ... }

...}

Page 13: Modern Component Design with Spring

Composable Annotations Revisited@Bean@Scope("session")@Primary@Retention(RetentionPolicy.RUNTIME)public @interface MyBean {}@Autowired@Qualifier("production")@Retention(RetentionPolicy.RUNTIME)public @interface MyAutowired {}@Value("#{systemProperties.databaseName}")@Retention(RetentionPolicy.RUNTIME)public @interface MyDatabaseName {}

Page 14: Modern Component Design with Spring

Standardized Annotations@ManagedBean@MySessionScopedpublic class MyBookAdminService implements BookAdminService { @Inject @Named("production") public MyBookAdminService(Provider<AccountRepository> ar) { ... }

@Transactional public BookUpdate updateBook(Addendum addendum) { ... }}

Page 15: Modern Component Design with Spring

JSR-330 and Co● @javax.inject.Inject is part of JSR-330

– "Dependency Injection for Java"– also defines @Scope, @Qualifier, @Named, and Provider interface

● @javax.transaction.Transactional is part of JTA 1.2 (EE 7)– finally a direct, independent equivalent of Spring's @Transactional – previously: just EJB 3.0's @javax.ejb.TransactionAttribute

● @javax.annotation.ManagedBean is part of JSR-250 v1.1– can be detected through classpath scanning

Page 16: Modern Component Design with Spring

JPA Support with Spring Transactions@Repositorypublic class MyAccountRepository { @PersistenceContext private EntityManager em; @Transactional public void storeAccount(Account account) { this.em.merge(account); }}

Page 17: Modern Component Design with Spring

Standardized vs. Spring-specific APIs● In general, we recommend the use of JSR-330 for DI

– JSR-330 @Inject is almost as capable as Spring's @Autowired– can mix and match with Spring's @Value, @Lazy, etc

● We also recommend the use of JPA 2.x– sufficiently expressive for many purposes now– can unwrap down to e.g. a Hibernate Session from a JPA EntityManager

● However, prefer Spring's stereotype and scoping model– composability is incredibly powerful

Page 18: Modern Component Design with Spring

Annotated MVC Controllers@Controllerpublic class MyMvcController { @RequestMapping(value = "/books/{id}", method = GET) public Book findBook(@PathVariable("id") long id) { return this.bookAdminService.findBook(id); }

@RequestMapping("/books/new") public void newBook(Book book) { this.bookAdminService.storeBook(book); }}

Page 19: Modern Component Design with Spring

Portlet MVC Controller@Controller@RequestMapping("EDIT")public class MyPortletController { @ActionMapping("delete") public void removeBook(@RequestParam("book") String bookId) { this.myService.deleteBook(bookId); }

@EventMapping("BookUpdate") public void updateBook(BookUpdateEvent bookUpdate) { this.myService.updateBook(…); }}

Page 20: Modern Component Design with Spring

STOMP on WebSocket@Controllerpublic class MyStompController { @SubscribeEvent("/positions") public List<PortfolioPosition> getPortfolios(Principal user) { ... }

@MessageMapping(value="/trade") public void executeTrade(Trade trade, Principal user) { ... }}

Page 21: Modern Component Design with Spring

Declarative Model Validationpublic class Book { @NotNull @Past private Date releaseDate;}

@RequestMapping("/books/new")public void newBook(@Valid Book book, BindingResult br) { ...}

Page 22: Modern Component Design with Spring

Declarative Formattingpublic class Book { @NotNull @Past @DateTimeFormat(iso=ISO.DATE) private Date releaseDate;}

public class Book { @DateTimeFormat(iso=ISO.DATE) private LocalDate releaseDate;}

Page 23: Modern Component Design with Spring

Declarative Scheduling@Asyncpublic void sendEmailNotifications() { ...}

@Asyncpublic Future<?> sendEmailNotificationsWithFuture() { return new AsyncResult(...);}

@Scheduled(cron = "0 0 12 * * ?")public void performTempFileCleanup() { ...}

Page 24: Modern Component Design with Spring

Declarative Caching@Cacheablepublic Owner loadOwner(int id) { ...}

@Cacheable(condition="name.length < 10")public Owner loadOwner(String name) { ...}

@CacheEvictpublic void deleteOwner(int id) { ...}

Page 25: Modern Component Design with Spring

Once Again: Spring Component Model Themes● Powerful annotated component model● Custom annotations through composition● Configuration classes and factory methods● Spring Expression Language● Flexible MVC/REST controller style● Declarative validation and formatting● Declarative scheduling and caching


Recommended