OPEN BATCH-1303: Support Spring 3.0 EL.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 = "}";
|
||||
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user