OPEN BATCH-1303: Support Spring 3.0 EL.

This commit is contained in:
dsyer
2009-06-22 07:22:13 +00:00
parent 026bb0665e
commit 9e60248dfc
7 changed files with 112 additions and 42 deletions

View File

@@ -103,7 +103,7 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
/**
* Flag to indicate that proxies should use dynamic subclassing. This allows
* classes with no interface to be proxied. Defaults to false.
* classes with no interface to be proxied. Defaults to false.
*
* @param proxyTargetClass set to true to have proxies created using dynamic
* subclasses
@@ -196,14 +196,15 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
"BeanFactory was not a BeanDefinitionRegistry, so StepScope cannot be used.");
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
Scopifier scopifier = new Scopifier(registry, name, proxyTargetClass);
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 (name.equals(definition.getScope())) {
if (scoped) {
new ExpressionHider(name, scoped).visitBeanDefinition(definition);
createScopedProxy(beanName, definition, registry, proxyTargetClass);
}
}
@@ -267,7 +268,9 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
private final String scope;
public Scopifier(BeanDefinitionRegistry registry, String scope, boolean proxyTargetClass) {
private final boolean scoped;
public Scopifier(BeanDefinitionRegistry registry, String scope, boolean proxyTargetClass, boolean scoped) {
super(new StringValueResolver() {
public String resolveStringValue(String value) {
return value;
@@ -276,32 +279,99 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
this.registry = registry;
this.proxyTargetClass = proxyTargetClass;
this.scope = scope;
this.scoped = scoped;
}
@Override
protected Object resolveValue(Object value) {
BeanDefinition definition = null;
String beanName = null;
if (value instanceof BeanDefinition) {
BeanDefinition definition = (BeanDefinition) value;
if (scope.equals(definition.getScope())) {
String beanName = BeanDefinitionReaderUtils.generateBeanName(definition, registry);
// Exit here so that nested inner bean definitions are not
// analysed
return createScopedProxy(beanName, definition, registry, proxyTargetClass);
}
definition = (BeanDefinition) value;
beanName = BeanDefinitionReaderUtils.generateBeanName(definition, registry);
}
else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder holder = (BeanDefinitionHolder) value;
BeanDefinition definition = holder.getBeanDefinition();
if (scope.equals(definition.getScope())) {
definition = holder.getBeanDefinition();
beanName = holder.getBeanName();
}
if (definition != null) {
boolean nestedScoped = scope.equals(definition.getScope());
boolean scopeChangeRequiresProxy = !scoped && nestedScoped;
new ExpressionHider(scope, nestedScoped).visitBeanDefinition(definition);
if (scopeChangeRequiresProxy) {
// Exit here so that nested inner bean definitions are not
// analysed
return createScopedProxy(holder.getBeanName(), definition, registry, proxyTargetClass);
return createScopedProxy(beanName, definition, registry, proxyTargetClass);
}
}
// Nested inner bean definitions are recursively analysed here
value = super.resolveValue(value);
return value;
}
}
/**
* Helper class to scan a bean definition hierarchy and hide placeholders
* from Spring EL.
*
* @author Dave Syer
*
*/
private static class ExpressionHider extends BeanDefinitionVisitor {
private static final String PLACEHOLDER_PREFIX = "#{";
private static final String PLACEHOLDER_SUFFIX = "}";
private static final String REPLACEMENT_PREFIX = "%{";
private final String scope;
private final boolean scoped;
private ExpressionHider(String scope, final boolean scoped) {
super(new StringValueResolver() {
public String resolveStringValue(String value) {
if (scoped && value.contains(PLACEHOLDER_PREFIX) && value.contains(PLACEHOLDER_SUFFIX)) {
value = value.replace(PLACEHOLDER_PREFIX, REPLACEMENT_PREFIX);
}
return value;
}
});
this.scope = scope;
this.scoped = scoped;
}
@Override
protected Object resolveValue(Object value) {
BeanDefinition definition = null;
if (value instanceof BeanDefinition) {
definition = (BeanDefinition) value;
}
else if (value instanceof BeanDefinitionHolder) {
BeanDefinitionHolder holder = (BeanDefinitionHolder) value;
definition = holder.getBeanDefinition();
}
if (definition != null) {
boolean scopeChange = !scope.equals(definition.getScope());
if (scopeChange) {
new ExpressionHider(definition.getScope(), !scoped).visitBeanDefinition(definition);
// Exit here so that nested inner bean definitions are not
// analysed by both vistors
return value;
}
}
// Nested inner bean definitions are recursively analysed here
value = super.resolveValue(value);
return value;
}
}
}

View File

@@ -57,7 +57,7 @@ public class PlaceholderTargetSource extends SimpleBeanTargetSource implements I
/**
* Key for placeholders to be replaced from the properties provided.
*/
private static final String PLACEHOLDER_PREFIX = "#{";
private static final String PLACEHOLDER_PREFIX = "%{";
private static final String PLACEHOLDER_SUFFIX = "}";

View File

@@ -68,26 +68,26 @@ public class PlaceholderTargetSourceErrorTests extends ContextFactorySupport {
@Test
public void testPartialReplaceSunnyDay() throws Exception {
Node target = (Node) createValue("name", "#{foo}-bar").getTarget();
Node target = (Node) createValue("name", "%{foo}-bar").getTarget();
assertEquals("bar-bar", target.getName());
}
@Test
public void testPartialReplaceMissingProperty() throws Exception {
Node target = (Node) createValue("name", "#{garbage}-bar").getTarget();
assertEquals("#{garbage}-bar", target.getName());
Node target = (Node) createValue("name", "%{garbage}-bar").getTarget();
assertEquals("%{garbage}-bar", target.getName());
}
@Test
public void testFullReplaceSunnyDay() throws Exception {
Node target = (Node) createValue("name", "#{foo}").getTarget();
Node target = (Node) createValue("name", "%{foo}").getTarget();
assertEquals("bar", target.getName());
}
@Test
public void testFullReplaceMissingProperty() throws Exception {
try {
Node target = (Node) createValue("name", "#{garbage}").getTarget();
Node target = (Node) createValue("name", "%{garbage}").getTarget();
assertEquals("bar", target.getName());
fail("Expected IllegalStateException");
}
@@ -99,26 +99,26 @@ public class PlaceholderTargetSourceErrorTests extends ContextFactorySupport {
@Test
public void testPartialReplaceIntegerToString() throws Exception {
Node target = (Node) createValue("name", "foo-#{integer}").getTarget();
Node target = (Node) createValue("name", "foo-%{integer}").getTarget();
assertEquals("foo-4321", target.getName());
}
@Test
public void testFullReplaceIntegerToString() throws Exception {
Node target = (Node) createValue("name", "#{integer}").getTarget();
Node target = (Node) createValue("name", "%{integer}").getTarget();
assertEquals("4321", target.getName());
}
@Test
public void testFullReplaceIntegerToLong() throws Exception {
Node target = (Node) createValue("value", "#{integer}").getTarget();
Node target = (Node) createValue("value", "%{integer}").getTarget();
assertEquals(4321L, target.getValue());
}
@Test
public void testFullReplaceIntegerToNode() throws Exception {
try {
Node target = (Node) createValue("parent", "#{integer}").getTarget();
Node target = (Node) createValue("parent", "%{integer}").getTarget();
assertEquals("4321", target.getParent());
fail("Expected IllegalArgumentException");
}

View File

@@ -19,7 +19,7 @@
<bean id="simpleTarget"
class="org.springframework.batch.core.scope.util.AsyncPlaceholderTargetSourceTests$Foo" autowire-candidate="false">
<property name="name" value="#{attributes[foo]}" />
<property name="name" value="%{attributes[foo]}" />
</bean>
<bean id="context"

View File

@@ -27,11 +27,11 @@
</bean>
<bean id="simpleTarget" class="org.springframework.batch.core.scope.util.MultipleContextPlaceholderTargetSourceTests$TestBean">
<property name="name" value="#{attributes[foo]}" />
<property name="name" value="%{attributes[foo]}" />
</bean>
<bean id="listTarget" class="org.springframework.batch.core.scope.util.MultipleContextPlaceholderTargetSourceTests$TestBean">
<property name="names" value="#{attributes[foo]}" />
<property name="names" value="%{attributes[foo]}" />
</bean>
<bean id="context"

View File

@@ -90,37 +90,37 @@
<bean id="simpleTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="#{map['foo.foo']}" />
<property name="name" value="%{map['foo.foo']}" />
</bean>
<bean id="compoundTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="#{foo}-bar" />
<property name="name" value="%{foo}-bar" />
</bean>
<bean id="refTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="parent" ref="#{foo}" />
<property name="parent" ref="%{foo}" />
</bean>
<bean id="valueTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="parent" value="#{parent}" />
<property name="parent" value="%{parent}" />
</bean>
<bean id="withLongTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="bar-#{long}" />
<property name="name" value="bar-%{long}" />
</bean>
<bean id="withIntegerTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="bar-#{integer}" />
<property name="name" value="bar-%{integer}" />
</bean>
<bean id="withListTarget"
@@ -128,9 +128,9 @@
lazy-init="true">
<property name="list">
<list>
<value>#{foo}</value>
<value>foo-#{integer}</value>
<value>bar-#{integer}</value>
<value>%{foo}</value>
<value>foo-%{integer}</value>
<value>bar-%{integer}</value>
</list>
</property>
</bean>
@@ -138,25 +138,25 @@
<bean id="withMultipleTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="bar-#{integer}-#{integer}" />
<property name="name" value="bar-%{integer}-%{integer}" />
</bean>
<bean id="withMultipleStartAndEndTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="#{integer}-#{integer}" />
<property name="name" value="%{integer}-%{integer}" />
</bean>
<bean id="withEmbeddedDateTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="name" value="bar-#{date}" />
<property name="name" value="bar-%{date}" />
</bean>
<bean id="withDateTarget"
class="org.springframework.batch.core.scope.util.PlaceholderTargetSourceTests$Foo"
lazy-init="true">
<property name="date" value="#{date}" />
<property name="date" value="%{date}" />
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">

View File

@@ -21,7 +21,7 @@
<bean id="simpleTarget"
class="org.springframework.batch.core.scope.util.SimplePlaceholderTargetSourceTests$Foo"
lazy-init="true" autowire-candidate="false">
<property name="name" value="#{foo}" />
<property name="name" value="%{foo}" />
</bean>
<bean id="context"