BATCH-1394: add support for SpEL with Spring 3.0 in step scope

This commit is contained in:
dsyer
2009-11-29 17:00:42 +00:00
parent 5ed1226627
commit 93be098a97
2 changed files with 60 additions and 35 deletions

View File

@@ -17,10 +17,12 @@ package org.springframework.batch.core.scope;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.batch.core.scope.context.StepContext;
import org.springframework.batch.core.scope.context.StepSynchronizationManager;
import org.springframework.batch.core.scope.util.PlaceholderProxyFactoryBean;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -33,6 +35,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringValueResolver;
/**
@@ -111,11 +114,17 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
public void setProxyTargetClass(boolean proxyTargetClass) {
this.proxyTargetClass = proxyTargetClass;
}
// Implement missing method from Spring 3.0 SPI.
/**
* If Spring 3.0 is available, this will be used to resolve expressions in
* step-scoped beans. This method is part of the Scope SPI in Spring 3.0,
* but should just be ignored by earlier versions of Spring.
*/
public Object resolveContextualObject(String key) {
StepContext context = getContext();
return context.getAttribute(key);
// TODO: support for attributes as well maybe (setters not exposed yet
// so not urgent).
return new BeanWrapperImpl(context).getPropertyValue(key);
}
/**
@@ -210,13 +219,19 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
Scopifier scopifier = new Scopifier(registry, name, proxyTargetClass, scoped);
scopifier.visitBeanDefinition(definition);
if (scoped) {
new ExpressionHider(name, scoped).visitBeanDefinition(definition);
if (!isSpringThree()) {
new ExpressionHider(name, scoped).visitBeanDefinition(definition);
}
createScopedProxy(beanName, definition, registry, proxyTargetClass);
}
}
}
private static boolean isSpringThree() {
return ReflectionUtils.findMethod(Scope.class, "resolveContextualObject", new Class<?>[] { String.class }) != null;
}
/**
* Public setter for the name property. This can then be used as a bean
* definition attribute, e.g. scope="step". Defaults to "step".
@@ -249,10 +264,19 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
// TODO: (for Batch 2.1) detect presence of Spring 3.0 and use
// ScopedProxyUtils instead
// Create the scoped proxy...
BeanDefinitionHolder proxyHolder = PlaceholderProxyFactoryBean.createScopedProxy(new BeanDefinitionHolder(
definition, beanName), registry, proxyTargetClass);
// ...and register it under the original target name
BeanDefinitionHolder proxyHolder;
if (isSpringThree()) {
proxyHolder = ScopedProxyUtils.createScopedProxy(new BeanDefinitionHolder(definition, beanName), registry,
proxyTargetClass);
}
else {
// Create the scoped proxy...
proxyHolder = PlaceholderProxyFactoryBean.createScopedProxy(new BeanDefinitionHolder(definition, beanName),
registry, proxyTargetClass);
// ...and register it under the original target name
}
registry.registerBeanDefinition(beanName, proxyHolder.getBeanDefinition());
return proxyHolder;
@@ -310,7 +334,7 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
if (scopeChangeRequiresProxy) {
// Exit here so that nested inner bean definitions are not
// analysed
return createScopedProxy(beanName, definition, registry, proxyTargetClass);
return createScopedProxy(beanName, definition, registry, proxyTargetClass);
}
}
@@ -368,7 +392,8 @@ public class StepScope implements Scope, BeanFactoryPostProcessor, Ordered {
String otherScope = definition.getScope();
boolean scopeChange = !scope.equals(otherScope);
if (scopeChange) {
new ExpressionHider(otherScope==null?scope:otherScope, !scoped).visitBeanDefinition(definition);
new ExpressionHider(otherScope == null ? scope : otherScope, !scoped)
.visitBeanDefinition(definition);
// Exit here so that nested inner bean definitions are not
// analysed by both visitors
return value;

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:beans="http://www.springframework.org/schema/beans"
<beans xmlns:batch="http://www.springframework.org/schema/batch"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-2.1.xsd">
<job id="pssJob">
<job id="pssJob" xmlns="http://www.springframework.org/schema/batch">
<step id="step1">
<tasklet>
<chunk reader="reader" writer="writer" commit-interval="1"/>
@@ -15,30 +15,30 @@
</step>
</job>
<job-repository id="jobRepository"/>
<batch:job-repository id="jobRepository"/>
<beans:bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<beans:property name="jobRepository" ref="jobRepository" />
</beans:bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<beans:bean id="reader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
<beans:property name="sql" value="select ID, NAME, VALUE from FOO where ID &gt;= ? and ID &lt;= ?"/>
<beans:property name="preparedStatementSetter" ref="pss"/>
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="rowMapper">
<beans:bean class="org.springframework.batch.core.resource.FooRowMapper"/>
</beans:property>
</beans:bean>
<bean id="reader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="sql" value="select ID, NAME, VALUE from FOO where ID &gt;= ? and ID &lt;= ?"/>
<property name="preparedStatementSetter" ref="pss"/>
<property name="dataSource" ref="dataSource"/>
<property name="rowMapper">
<bean class="org.springframework.batch.core.resource.FooRowMapper"/>
</property>
</bean>
<beans:bean id="pss" class="org.springframework.batch.core.resource.ListPreparedStatementSetter" scope="step">
<beans:property name="parameters">
<beans:list>
<beans:value>#{jobParameters[min.id]}</beans:value>
<beans:value>#{jobParameters[max.id]}</beans:value>
</beans:list>
</beans:property>
</beans:bean>
<bean id="pss" class="org.springframework.batch.core.resource.ListPreparedStatementSetter" scope="step">
<property name="parameters">
<list>
<value>#{jobParameters['min.id']}</value>
<value>#{jobParameters['max.id']}</value>
</list>
</property>
</bean>
<beans:bean id="writer" class="org.springframework.batch.core.resource.ListPreparedStatementSetterTests$FooStoringItemWriter"/>
<bean id="writer" class="org.springframework.batch.core.resource.ListPreparedStatementSetterTests$FooStoringItemWriter"/>
</beans:beans>
</beans>