From 2d0e0c22aca3a2d5e31ea4f76374c963333ca150 Mon Sep 17 00:00:00 2001 From: jpraet Date: Wed, 14 Aug 2013 22:17:14 +0200 Subject: [PATCH] BATCH-2053: Allow overriding step scope proxy-target-class flag on bean level with aop:scoped-proxy --- .../batch/core/scope/StepScope.java | 20 ++- ...xyTargetClassOverrideIntegrationTests.java | 143 ++++++++++++++++++ ...tClassOverrideIntegrationTests-context.xml | 69 +++++++++ 3 files changed, 224 insertions(+), 8 deletions(-) create mode 100644 spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java create mode 100644 spring-batch-core/src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests-context.xml diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java index 644b3617a..718630a68 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/scope/StepScope.java @@ -75,6 +75,8 @@ import org.springframework.util.StringValueResolver; * @since 2.0 */ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered { + + private static final String TARGET_NAME_PREFIX = "scopedTarget."; private Log logger = LogFactory.getLog(getClass()); @@ -232,15 +234,17 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; for (String beanName : beanFactory.getBeanDefinitionNames()) { - BeanDefinition definition = beanFactory.getBeanDefinition(beanName); - // Replace this or any of its inner beans with scoped proxy if it - // has this scope - boolean scoped = name.equals(definition.getScope()); - Scopifier scopifier = new Scopifier(registry, name, proxyTargetClass, scoped); - scopifier.visitBeanDefinition(definition); + if (!beanName.startsWith(TARGET_NAME_PREFIX)) { + BeanDefinition definition = beanFactory.getBeanDefinition(beanName); + // Replace this or any of its inner beans with scoped proxy if it + // has this scope + boolean scoped = name.equals(definition.getScope()); + Scopifier scopifier = new Scopifier(registry, name, proxyTargetClass, scoped); + scopifier.visitBeanDefinition(definition); - if (scoped && !definition.isAbstract()) { - createScopedProxy(beanName, definition, registry, proxyTargetClass); + if (scoped && !definition.isAbstract()) { + createScopedProxy(beanName, definition, registry, proxyTargetClass); + } } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java new file mode 100644 index 000000000..f6cfc221c --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests.java @@ -0,0 +1,143 @@ +package org.springframework.batch.core.scope; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.aop.support.AopUtils; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.scope.context.StepSynchronizationManager; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.ListableBeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class StepScopeProxyTargetClassOverrideIntegrationTests implements BeanFactoryAware { + + private static final String JDK_PROXY_TO_STRING_REGEX = "class .*\\$Proxy\\d+"; + + private static final String CGLIB_PROXY_TO_STRING_REGEX = "class .*\\$EnhancerByCGLIB.*"; + + @Autowired + @Qualifier("simple") + private TestCollaborator simple; + + @Autowired + @Qualifier("simpleProxyTargetClassTrue") + private TestCollaborator simpleProxyTargetClassTrue; + + @Autowired + @Qualifier("simpleProxyTargetClassFalse") + private Collaborator simpleProxyTargetClassFalse; + + @Autowired + @Qualifier("nested") + private Step nested; + + @Autowired + @Qualifier("nestedProxyTargetClassTrue") + private Step nestedProxyTargetClassTrue; + + @Autowired + @Qualifier("nestedProxyTargetClassFalse") + private Step nestedProxyTargetClassFalse; + + private StepExecution stepExecution; + + private ListableBeanFactory beanFactory; + + private int beanCount; + + @Override + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = (ListableBeanFactory) beanFactory; + } + + @Before + public void start() { + + StepSynchronizationManager.close(); + TestStep.reset(); + stepExecution = new StepExecution("foo", new JobExecution(11L), 123L); + + ExecutionContext executionContext = new ExecutionContext(); + executionContext.put("foo", "bar"); + + stepExecution.setExecutionContext(executionContext); + StepSynchronizationManager.register(stepExecution); + + beanCount = beanFactory.getBeanDefinitionCount(); + + } + + @After + public void cleanUp() { + StepSynchronizationManager.close(); + // Check that all temporary bean definitions are cleaned up + assertEquals(beanCount, beanFactory.getBeanDefinitionCount()); + } + + @Test + public void testSimple() throws Exception { + assertTrue(AopUtils.isCglibProxy(simple)); + assertEquals("bar", simple.getName()); + } + + @Test + public void testSimpleProxyTargetClassTrue() throws Exception { + assertTrue(AopUtils.isCglibProxy(simpleProxyTargetClassTrue)); + assertEquals("bar", simpleProxyTargetClassTrue.getName()); + } + + @Test + public void testSimpleProxyTargetClassFalse() throws Exception { + assertTrue(AopUtils.isJdkDynamicProxy(simpleProxyTargetClassFalse)); + assertEquals("bar", simpleProxyTargetClassFalse.getName()); + } + + @Test + public void testNested() throws Exception { + nested.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + assertTrue(TestStep.getContext().attributeNames().length > 0); + String collaborator = (String) TestStep.getContext().getAttribute("collaborator"); + assertNotNull(collaborator); + assertEquals("foo", collaborator); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertNotNull(parent); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) + .matches(CGLIB_PROXY_TO_STRING_REGEX)); + } + + @Test + public void testNestedProxyTargetClassTrue() throws Exception { + nestedProxyTargetClassTrue.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) + .matches(CGLIB_PROXY_TO_STRING_REGEX)); + } + + @Test + public void testNestedProxyTargetClassFalse() throws Exception { + nestedProxyTargetClassFalse.execute(new StepExecution("foo", new JobExecution(11L), 31L)); + String parent = (String) TestStep.getContext().getAttribute("parent"); + assertEquals("bar", parent); + assertTrue("Scoped proxy not created", ((String) TestStep.getContext().getAttribute("parent.class")) + .matches(JDK_PROXY_TO_STRING_REGEX)); + } + +} diff --git a/spring-batch-core/src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests-context.xml b/spring-batch-core/src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests-context.xml new file mode 100644 index 000000000..037c824c2 --- /dev/null +++ b/spring-batch-core/src/test/resources/org/springframework/batch/core/scope/StepScopeProxyTargetClassOverrideIntegrationTests-context.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file