Support for transactional event listener
Update the application event listener infrastructure to support events that are processed according to a transactional phase. Introduce EventListenerFactory that can be implemented to provide support for additional event listener types. TransactionalEventListener is a new annotation that can be used in lieu of the regular EventListener. Its related factory implementation is registered in the context automatically via @EnableTransactionManagement or <tx:annotation-driven/> By default, a TransactionalEventListener is invoked when the transaction has completed successfully (i.e. AFTER_COMMIT). Additional phases are provided to handle BEFORE_COMMIT and AFTER_ROLLBACK events. If no transaction is running, such listener is not invoked at all unless the `fallbackExecution` flag has been explicitly set. Issue: SPR-12080
This commit is contained in:
@@ -55,7 +55,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(11, beanCount);
|
||||
assertEquals(12, beanCount);
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
assertTrue(context.containsBean("stubFooDao"));
|
||||
@@ -67,6 +67,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
context.refresh();
|
||||
FooServiceImpl service = context.getBean("fooServiceImpl", FooServiceImpl.class);
|
||||
assertTrue(context.getDefaultListableBeanFactory().containsSingleton("myNamedComponent"));
|
||||
@@ -99,7 +100,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(11, beanCount);
|
||||
assertEquals(12, beanCount);
|
||||
scanner.scan(BASE_PACKAGE);
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
@@ -219,12 +220,13 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(6, beanCount);
|
||||
assertEquals(7, beanCount);
|
||||
assertTrue(context.containsBean("messageBean"));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -233,7 +235,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, false);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(6, beanCount);
|
||||
assertEquals(7, beanCount);
|
||||
assertTrue(context.containsBean("messageBean"));
|
||||
assertFalse(context.containsBean("serviceInvocationCounter"));
|
||||
assertFalse(context.containsBean("fooServiceImpl"));
|
||||
@@ -244,6 +246,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -252,7 +255,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
|
||||
scanner.addIncludeFilter(new AnnotationTypeFilter(CustomComponent.class));
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(12, beanCount);
|
||||
assertEquals(13, beanCount);
|
||||
assertTrue(context.containsBean("messageBean"));
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
@@ -263,6 +266,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -271,7 +275,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
|
||||
scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class));
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(10, beanCount);
|
||||
assertEquals(11, beanCount);
|
||||
assertFalse(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("fooServiceImpl"));
|
||||
assertTrue(context.containsBean("stubFooDao"));
|
||||
@@ -289,7 +293,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
|
||||
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(10, beanCount);
|
||||
assertEquals(11, beanCount);
|
||||
assertFalse(context.containsBean("fooServiceImpl"));
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("stubFooDao"));
|
||||
@@ -299,6 +303,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -326,7 +331,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
scanner.addExcludeFilter(new AssignableTypeFilter(FooService.class));
|
||||
scanner.addExcludeFilter(new AnnotationTypeFilter(Aspect.class));
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(9, beanCount);
|
||||
assertEquals(10, beanCount);
|
||||
assertFalse(context.containsBean("fooServiceImpl"));
|
||||
assertFalse(context.containsBean("serviceInvocationCounter"));
|
||||
assertTrue(context.containsBean("stubFooDao"));
|
||||
@@ -336,6 +341,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -344,7 +350,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(11, beanCount);
|
||||
assertEquals(12, beanCount);
|
||||
assertFalse(context.containsBean("fooServiceImpl"));
|
||||
assertTrue(context.containsBean("fooService"));
|
||||
assertTrue(context.containsBean("serviceInvocationCounter"));
|
||||
@@ -355,6 +361,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_PROCESSOR_BEAN_NAME));
|
||||
assertTrue(context.containsBean(AnnotationConfigUtils.EVENT_LISTENER_FACTORY_BEAN_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -364,7 +371,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
GenericApplicationContext multiPackageContext = new GenericApplicationContext();
|
||||
ClassPathBeanDefinitionScanner multiPackageScanner = new ClassPathBeanDefinitionScanner(multiPackageContext);
|
||||
int singlePackageBeanCount = singlePackageScanner.scan(BASE_PACKAGE);
|
||||
assertEquals(11, singlePackageBeanCount);
|
||||
assertEquals(12, singlePackageBeanCount);
|
||||
multiPackageScanner.scan(BASE_PACKAGE, "org.springframework.dao.annotation");
|
||||
// assertTrue(multiPackageBeanCount > singlePackageBeanCount);
|
||||
}
|
||||
@@ -375,7 +382,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
int initialBeanCount = context.getBeanDefinitionCount();
|
||||
int scannedBeanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(11, scannedBeanCount);
|
||||
assertEquals(12, scannedBeanCount);
|
||||
assertEquals(scannedBeanCount, context.getBeanDefinitionCount() - initialBeanCount);
|
||||
int addedBeanCount = scanner.scan("org.springframework.aop.aspectj.annotation");
|
||||
assertEquals(initialBeanCount + scannedBeanCount + addedBeanCount, context.getBeanDefinitionCount());
|
||||
@@ -388,7 +395,7 @@ public class ClassPathBeanDefinitionScannerTests {
|
||||
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
|
||||
scanner.setBeanNameGenerator(new TestBeanNameGenerator());
|
||||
int beanCount = scanner.scan(BASE_PACKAGE);
|
||||
assertEquals(11, beanCount);
|
||||
assertEquals(12, beanCount);
|
||||
context.refresh();
|
||||
|
||||
FooServiceImpl fooService = context.getBean("fooService", FooServiceImpl.class);
|
||||
|
||||
Reference in New Issue
Block a user