Skip to content

Commit b0acb58

Browse files
committed
Merge pull request spring-projects#125 from jeffbrown/beanbuilder
GRAILS-4995 - Improve the handling of List and Map ctor args
2 parents c463fd0 + a0b3da7 commit b0acb58

File tree

2 files changed

+101
-69
lines changed

2 files changed

+101
-69
lines changed

spring-lang-groovy/src/main/java/org/springframework/context/groovy/GroovyBeanDefinitionReader.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,13 @@ else if(args[0] instanceof Closure) {
714714
protected List resolveConstructorArguments(Object[] args, int start, int end) {
715715
Object[] constructorArgs = subarray(args, start, end);
716716
filterGStringReferences(constructorArgs);
717+
for(int i = 0; i < constructorArgs.length; i++) {
718+
if(constructorArgs[i] instanceof List) {
719+
constructorArgs[i] = manageListIfNecessary(constructorArgs[i]);
720+
} else if(constructorArgs[i] instanceof Map){
721+
constructorArgs[i] = manageMapIfNecessary(constructorArgs[i]);
722+
}
723+
}
717724
List constructorArgsList = Arrays.asList(constructorArgs);
718725
return constructorArgsList;
719726
}

spring-lang-groovy/src/test/groovy/org/springframework/context/groovy/GroovyBeanDefinitionReaderTests.groovy

Lines changed: 94 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -133,69 +133,61 @@ class GroovyBeanDefinitionReaderTests extends GroovyTestCase {
133133
void testUseTwoSpringNamespaces() {
134134
def beanReader = new GroovyBeanDefinitionReader()
135135

136-
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder()
137-
try {
138-
139-
builder.bind("bar", "success")
140-
builder.activate()
141-
TestScope scope = new TestScope()
142-
143-
GenericApplicationContext appCtx = beanReader.getSpringConfig().getUnrefreshedApplicationContext()
144-
appCtx.getBeanFactory().registerScope("test", scope)
145-
beanReader.beans {
146-
xmlns aop:"http://www.springframework.org/schema/aop"
147-
xmlns jee:"http://www.springframework.org/schema/jee"
148-
scopedList(ArrayList) { bean ->
149-
bean.scope = "test"
150-
aop.'scoped-proxy'()
151-
}
152-
153-
jee.'jndi-lookup'(id:"foo", 'jndi-name':"bar")
136+
TestScope scope = new TestScope()
154137

138+
GenericApplicationContext appCtx = beanReader.getSpringConfig().getUnrefreshedApplicationContext()
139+
appCtx.getBeanFactory().registerScope("test", scope)
140+
beanReader.beans {
141+
xmlns aop:"http://www.springframework.org/schema/aop"
142+
xmlns util:"http://www.springframework.org/schema/util"
143+
scopedList(ArrayList) { bean ->
144+
bean.scope = "test"
145+
aop.'scoped-proxy'()
155146
}
147+
util.list(id: 'foo') {
148+
value 'one'
149+
value 'two'
150+
}
151+
}
156152

157-
appCtx = beanReader.createApplicationContext()
158-
159-
assertEquals "success", appCtx.getBean("foo")
160-
161-
assertNotNull appCtx.getBean("scopedList")
162-
assertNotNull appCtx.getBean("scopedList").size()
163-
assertNotNull appCtx.getBean("scopedList").size()
153+
appCtx = beanReader.createApplicationContext()
164154

165-
// should only be true because bean not initialized until proxy called
166-
assertEquals 2, scope.instanceCount
155+
assert ['one', 'two'] == appCtx.getBean("foo")
167156

168-
beanReader = new GroovyBeanDefinitionReader()
157+
assertNotNull appCtx.getBean("scopedList")
158+
assertNotNull appCtx.getBean("scopedList").size()
159+
assertNotNull appCtx.getBean("scopedList").size()
169160

170-
appCtx = beanReader.getSpringConfig().getUnrefreshedApplicationContext()
171-
appCtx.getBeanFactory().registerScope("test", scope)
172-
beanReader.beans {
173-
xmlns aop:"http://www.springframework.org/schema/aop",
174-
jee:"http://www.springframework.org/schema/jee"
175-
scopedList(ArrayList) { bean ->
176-
bean.scope = "test"
177-
aop.'scoped-proxy'()
178-
}
161+
// should only be true because bean not initialized until proxy called
162+
assertEquals 2, scope.instanceCount
179163

180-
jee.'jndi-lookup'(id:"foo", 'jndi-name':"bar")
164+
beanReader = new GroovyBeanDefinitionReader()
181165

166+
appCtx = beanReader.getSpringConfig().getUnrefreshedApplicationContext()
167+
appCtx.getBeanFactory().registerScope("test", scope)
168+
beanReader.beans {
169+
xmlns aop:"http://www.springframework.org/schema/aop",
170+
util:"http://www.springframework.org/schema/util"
171+
scopedList(ArrayList) { bean ->
172+
bean.scope = "test"
173+
aop.'scoped-proxy'()
182174
}
183-
appCtx = beanReader.createApplicationContext()
184-
185-
assertEquals "success", appCtx.getBean("foo")
186175

187-
assertNotNull appCtx.getBean("scopedList")
188-
assertNotNull appCtx.getBean("scopedList").size()
189-
assertNotNull appCtx.getBean("scopedList").size()
190-
191-
// should only be true because bean not initialized until proxy called
192-
assertEquals 4, scope.instanceCount
176+
util.list(id: 'foo') {
177+
value 'one'
178+
value 'two'
179+
}
180+
}
181+
appCtx = beanReader.createApplicationContext()
182+
183+
assert ['one', 'two'] == appCtx.getBean("foo")
193184

185+
assertNotNull appCtx.getBean("scopedList")
186+
assertNotNull appCtx.getBean("scopedList").size()
187+
assertNotNull appCtx.getBean("scopedList").size()
194188

195-
}
196-
finally {
197-
builder.deactivate()
198-
}
189+
// should only be true because bean not initialized until proxy called
190+
assertEquals 4, scope.instanceCount
199191
}
200192

201193
void testSpringAOPSupport() {
@@ -262,24 +254,17 @@ class GroovyBeanDefinitionReaderTests extends GroovyTestCase {
262254
void testSpringNamespaceBean() {
263255
def beanReader = new GroovyBeanDefinitionReader()
264256

265-
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder()
266-
try {
267-
268-
builder.bind("bar", "success")
269-
builder.activate()
270-
271-
beanReader.beans {
272-
xmlns jee:"http://www.springframework.org/schema/jee"
273-
jee.'jndi-lookup'(id:"foo", 'jndi-name':"bar")
257+
beanReader.beans {
258+
xmlns util: 'http://www.springframework.org/schema/util'
259+
util.list(id: 'foo') {
260+
value 'one'
261+
value 'two'
274262
}
275-
276-
ApplicationContext appCtx = beanReader.createApplicationContext()
277-
278-
assertEquals "success", appCtx.getBean("foo")
279-
}
280-
finally {
281-
builder.deactivate()
282263
}
264+
265+
def ctx = beanReader.createApplicationContext()
266+
267+
assert ['one', 'two'] == ctx.getBean('foo')
283268
}
284269

285270
void testNamedArgumentConstructor() {
@@ -772,9 +757,7 @@ beanReader.createApplicationContext()
772757
assertEquals "Fred", appCtx.getBean("personA").name
773758
}
774759

775-
// test for GRAILS-4995
776760
void testListOfBeansAsConstructorArg() {
777-
if(notYetImplemented()) return
778761
def beanReader = new GroovyBeanDefinitionReader()
779762

780763
beanReader.beans {
@@ -790,6 +773,34 @@ beanReader.createApplicationContext()
790773
assert ctx.containsBean('someotherbean2')
791774
assert ctx.containsBean('somebean')
792775
}
776+
777+
void testBeanWithListAndMapConstructor() {
778+
def beanReader = new GroovyBeanDefinitionReader()
779+
beanReader.beans {
780+
bart(Bean1) {
781+
person = "bart"
782+
age = 11
783+
}
784+
lisa(Bean1) {
785+
person = "lisa"
786+
age = 9
787+
}
788+
789+
beanWithList(Bean5, [bart, lisa])
790+
791+
// test runtime references both as ref() and as plain name
792+
beanWithMap(Bean6, [bart:bart, lisa:ref('lisa')])
793+
}
794+
def ctx = beanReader.createApplicationContext()
795+
796+
def beanWithList = ctx.getBean("beanWithList")
797+
assertEquals 2, beanWithList.people.size()
798+
assertEquals "bart", beanWithList.people[0].person
799+
800+
def beanWithMap = ctx.getBean("beanWithMap")
801+
assertEquals 9, beanWithMap.peopleByName.lisa.age
802+
assertEquals "bart", beanWithMap.peopleByName.bart.person
803+
}
793804

794805
void testAnonymousInnerBeanViaBeanMethod() {
795806
def beanReader = new GroovyBeanDefinitionReader()
@@ -903,6 +914,20 @@ class Bean4 {
903914
}
904915
String person
905916
}
917+
// bean with List-valued constructor arg
918+
class Bean5 {
919+
Bean5(List<Bean1> people) {
920+
this.people = people
921+
}
922+
List<Bean1> people
923+
}
924+
// bean with Map-valued constructor arg
925+
class Bean6 {
926+
Bean6(Map<String, Bean1> peopleByName) {
927+
this.peopleByName = peopleByName
928+
}
929+
Map<String, Bean1> peopleByName
930+
}
906931
// a factory bean
907932
class Bean1Factory {
908933
Bean1 newInstance() {

0 commit comments

Comments
 (0)