Skip to content

Commit 70155e9

Browse files
committed
KeyGenerators should not return a plain array parameter as raw key but rather always handle that case in a deepHashCode fashion
Issue: SPR-11505 (cherry picked from commit e50cff4)
1 parent 7e2a214 commit 70155e9

File tree

2 files changed

+132
-10
lines changed

2 files changed

+132
-10
lines changed

spring-context/src/main/java/org/springframework/cache/interceptor/DefaultKeyGenerator.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2011 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,8 +17,7 @@
1717
package org.springframework.cache.interceptor;
1818

1919
import java.lang.reflect.Method;
20-
21-
import org.springframework.cache.interceptor.KeyGenerator;
20+
import java.util.Arrays;
2221

2322
/**
2423
* Default key generator. Returns {@value #NO_PARAM_KEY} if no
@@ -29,25 +28,29 @@
2928
*
3029
* @author Costin Leau
3130
* @author Chris Beams
31+
* @author Juergen Hoeller
3232
* @since 3.1
3333
*/
3434
public class DefaultKeyGenerator implements KeyGenerator {
3535

3636
public static final int NO_PARAM_KEY = 0;
37+
3738
public static final int NULL_PARAM_KEY = 53;
3839

3940
public Object generate(Object target, Method method, Object... params) {
40-
if (params.length == 1) {
41-
return (params[0] == null ? NULL_PARAM_KEY : params[0]);
42-
}
4341
if (params.length == 0) {
4442
return NO_PARAM_KEY;
4543
}
46-
int hashCode = 17;
47-
for (Object object : params) {
48-
hashCode = 31 * hashCode + (object == null ? NULL_PARAM_KEY : object.hashCode());
44+
if (params.length == 1) {
45+
Object param = params[0];
46+
if (param == null) {
47+
return NULL_PARAM_KEY;
48+
}
49+
if (!param.getClass().isArray()) {
50+
return param;
51+
}
4952
}
50-
return Integer.valueOf(hashCode);
53+
return Arrays.deepHashCode(params);
5154
}
5255

5356
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2002-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cache.interceptor;
18+
19+
import org.junit.Test;
20+
21+
import static org.hamcrest.Matchers.*;
22+
import static org.junit.Assert.*;
23+
24+
/**
25+
* Tests for {@link DefaultKeyGenerator}.
26+
*
27+
* @author Juergen Hoeller
28+
* @author Stephane Nicoll
29+
*/
30+
public class DefaultKeyGeneratorTests {
31+
32+
private final DefaultKeyGenerator generator = new DefaultKeyGenerator();
33+
34+
35+
@Test
36+
public void noValues() {
37+
Object k1 = generateKey(new Object[] {});
38+
Object k2 = generateKey(new Object[] {});
39+
Object k3 = generateKey(new Object[] { "different" });
40+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
41+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
42+
assertThat(k1, equalTo(k2));
43+
assertThat(k1, not(equalTo(k3)));
44+
}
45+
46+
@Test
47+
public void singleValue(){
48+
Object k1 = generateKey(new Object[] { "a" });
49+
Object k2 = generateKey(new Object[] { "a" });
50+
Object k3 = generateKey(new Object[] { "different" });
51+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
52+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
53+
assertThat(k1, equalTo(k2));
54+
assertThat(k1, not(equalTo(k3)));
55+
assertThat(k1, equalTo((Object) "a"));
56+
}
57+
58+
@Test
59+
public void multipleValues() {
60+
Object k1 = generateKey(new Object[] { "a", 1, "b" });
61+
Object k2 = generateKey(new Object[] { "a", 1, "b" });
62+
Object k3 = generateKey(new Object[] { "b", 1, "a" });
63+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
64+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
65+
assertThat(k1, equalTo(k2));
66+
assertThat(k1, not(equalTo(k3)));
67+
}
68+
69+
@Test
70+
public void singleNullValue() {
71+
Object k1 = generateKey(new Object[] { null });
72+
Object k2 = generateKey(new Object[] { null });
73+
Object k3 = generateKey(new Object[] { "different" });
74+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
75+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
76+
assertThat(k1, equalTo(k2));
77+
assertThat(k1, not(equalTo(k3)));
78+
assertThat(k1, instanceOf(Integer.class));
79+
}
80+
81+
@Test
82+
public void multipleNullValues() {
83+
Object k1 = generateKey(new Object[] { "a", null, "b", null });
84+
Object k2 = generateKey(new Object[] { "a", null, "b", null });
85+
Object k3 = generateKey(new Object[] { "a", null, "b" });
86+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
87+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
88+
assertThat(k1, equalTo(k2));
89+
assertThat(k1, not(equalTo(k3)));
90+
}
91+
92+
@Test
93+
public void plainArray() {
94+
Object k1 = generateKey(new Object[] { new String[]{"a", "b"} });
95+
Object k2 = generateKey(new Object[] { new String[]{"a", "b"} });
96+
Object k3 = generateKey(new Object[] { new String[]{"b", "a"} });
97+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
98+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
99+
assertThat(k1, equalTo(k2));
100+
assertThat(k1, not(equalTo(k3)));
101+
}
102+
103+
@Test
104+
public void arrayWithExtraParameter() {
105+
Object k1 = generateKey(new Object[] { new String[]{"a", "b"}, "c" });
106+
Object k2 = generateKey(new Object[] { new String[]{"a", "b"}, "c" });
107+
Object k3 = generateKey(new Object[] { new String[]{"b", "a"}, "c" });
108+
assertThat(k1.hashCode(), equalTo(k2.hashCode()));
109+
assertThat(k1.hashCode(), not(equalTo(k3.hashCode())));
110+
assertThat(k1, equalTo(k2));
111+
assertThat(k1, not(equalTo(k3)));
112+
}
113+
114+
115+
private Object generateKey(Object[] arguments) {
116+
return this.generator.generate(null, null, arguments);
117+
}
118+
119+
}

0 commit comments

Comments
 (0)