// Return JSON without Jackson mapping classes @RequestMapping("/users") public @ResponseBody Map getUsers () { Map map = new HashMap(); map.put("user", "Clark Kent"); return map; } // Autowiring multiple Beans of same type into a Java List @Autowired private List beans; // Get a Bean out of the Spring Application Context ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); MyBean myFirstBean = context.getBean("myFirstBean", MyBean.class); // By default all Spring managed Beans are Singletons (@Scope("singleton")) MyBean bean1 = context.getBean("myBean", MyBean.class); MyBean bean2 = context.getBean("myBean", MyBean.class); bean1 == bean2; // => true // Create a new Bean on each autowiring and each context.getBean() call @Bean @Scope("prototype") public MyBean myBean() { return new MyBean(); } MyBean bean1 = context.getBean("myBean", MyBean.class); MyBean bean2 = context.getBean("myBean", MyBean.class); bean1 == bean2; // => false // In a web app (Spring MVC) there are two more Scopes: "request" and "session" // It is also possible to define a custom Scope // Calling a @Bean annotated method multiple times // result in the exact same instance of the Bean every time it gets called // as the scope is "singleton" by default @Configuration public class MyConfig { @Bean public MyBean myBean() { return new MyBean(); } public void myTestMethod() { MyBean myBean1 = myBean(); MyBean myBean2 = myBean(); myBean1 == myBean2 // => true } } // This is achieved by Spring automatically subclassing the MyConfig Class // and overriding the myBean() method somehow like this: public class SpringMyConfig extends MyConfig { @Override public MyBean myBean() { if (myBean already in context) { return myBean; } else { MyBean myBean = super.myBean(); context.add(myBean); return myBean; } } } // Call a method right after the constructor + setter methods and a method before the destruction of a bean @Bean(initMethod = "myStart", destroyMethod = "myEnd") public MyBean myBean() { return new MyBean(); } public class MyBean { public void myStart() { // do something } public void myEnd() { // do something } } // OR: on the Bean class directly (JSR 330 -> not hardwired to Spring) - Only works with singleton scoped Beans: public class MyBean { @PostConstruct public void myStart() { // do something } @PreDestroy public void myEnd() { // do something } } // @Transactional - manages a transaction manager // // Spring doesn't provide any transaction managers itself. // It provides hooks to them. // // Databases have their own transaction managers which will // be used by Spring. // // Spring requests different features of the underlying transaction // managers since not all provide the same functionality (e.g. Rollback on Timeout) // // For @Transactional to work there has to be a Platform Transaction Manager Bean being declared // It provides the hook into the underlying transactional system. // Apply @Transactional to all methods of a class (can be overridden with @Transactional on a specific method) @Transactional public class MyBean { public void doStuff() { } public void doOtherStuff() { } } // Properties of the @Transactional Annotation // isolation - enum for isolation levels // propagation - enum for propagation levels // readOnly - boolean to request a readOnly transaction // timeout - integer for a timout period // value - String for the name of the transaction manager Bean (Default is: "transactionManager") // rollbackFor - List of Exception classes which must trigger a rollback // rollbackForClassName - List of Strings with classnames of Exception classes which must trigger a rollback // noRollbackFor - List of Exception classes which must not trigger a rollback // noRollbackForClassName - List of Strings with classnames of Exception classes which must not trigger a rollback // PlatformTransactionManager - Interface which is implemented by several Transaction Managers // (e.g. JmsTransactionManager, JpaTransactionManager) // it has commit() and rollback() as methods // 3 Steps to achieve transactional behaviour: // 1. Set @Transactional on a @Service Bean to achieve that each service method is transactional @Service @Transactional public class MyService { @Autowired private MyRepository myRepo; } // 2. In MyConfig declare a transaction manager // 3. Annotate MyConfig with @EnableTransactionManagement // This tells Spring to generate the transactional Proxies // The equivalent in XML configuration is @Configuration @EnableTransactionManagement public class MyConfig { @Bean(name = "transactionManager") @Profile("test") public PlatformTransactionManager transactionManagerForTest() { return new DataSourceTransactionManager(dataSourceForTest()); } @Bean(name = "dataSource", destroyMethod = "shutdown") @Profile("test") public DataSource dataSourceForTest() { return new EmbeddedDatabaseBuilder() .generateUniqueName(true) .setType(EmbeddedDatabaseType.H2) .setScriptEncoding("UTF-8") .ignoreFailedDrops(true) .addScript("schema.sql") .addScripts("data.sql") .build(); } }