16
16
17
17
package org .springframework .test .web .servlet .samples .spr ;
18
18
19
+ import java .util .Map ;
19
20
import java .util .concurrent .atomic .AtomicInteger ;
20
21
21
22
import org .junit .Before ;
25
26
import org .springframework .beans .factory .annotation .Autowired ;
26
27
import org .springframework .context .annotation .Bean ;
27
28
import org .springframework .context .annotation .Configuration ;
29
+ import org .springframework .context .annotation .Scope ;
28
30
import org .springframework .stereotype .Controller ;
29
31
import org .springframework .test .context .junit4 .SpringRunner ;
30
32
import org .springframework .test .context .web .WebAppConfiguration ;
33
35
import org .springframework .web .bind .annotation .ControllerAdvice ;
34
36
import org .springframework .web .bind .annotation .GetMapping ;
35
37
import org .springframework .web .bind .annotation .ModelAttribute ;
38
+ import org .springframework .web .bind .annotation .RequestParam ;
36
39
import org .springframework .web .context .WebApplicationContext ;
37
40
import org .springframework .web .context .annotation .RequestScope ;
38
41
import org .springframework .web .servlet .config .annotation .EnableWebMvc ;
@@ -64,21 +67,53 @@ public class ControllerAdviceIntegrationTests {
64
67
@ Before
65
68
public void setUpMockMvc () {
66
69
this .mockMvc = webAppContextSetup (wac ).build ();
70
+ resetCounters ();
67
71
}
68
72
69
73
@ Test
70
74
public void controllerAdviceIsAppliedOnlyOnce () throws Exception {
71
- assertEquals (0 , SingletonControllerAdvice .counter .get ());
72
- assertEquals (0 , RequestScopedControllerAdvice .counter .get ());
75
+ this .mockMvc .perform (get ("/test" ).param ("requestParam" , "foo" ))//
76
+ .andExpect (status ().isOk ())//
77
+ .andExpect (forwardedUrl ("singleton:1;prototype:1;request-scoped:1;requestParam:foo" ));
78
+
79
+ assertEquals (1 , SingletonControllerAdvice .invocationCount .get ());
80
+ assertEquals (1 , PrototypeControllerAdvice .invocationCount .get ());
81
+ assertEquals (1 , RequestScopedControllerAdvice .invocationCount .get ());
82
+ }
83
+
84
+ @ Test
85
+ public void prototypeAndRequestScopedControllerAdviceBeansAreNotCached () throws Exception {
86
+ this .mockMvc .perform (get ("/test" ).param ("requestParam" , "foo" ))//
87
+ .andExpect (status ().isOk ())//
88
+ .andExpect (forwardedUrl ("singleton:1;prototype:1;request-scoped:1;requestParam:foo" ));
89
+
90
+ // singleton @ControllerAdvice beans should not be instantiated again.
91
+ assertEquals (0 , SingletonControllerAdvice .instanceCount .get ());
92
+ // prototype and request-scoped @ControllerAdvice beans should be instantiated once per request.
93
+ assertEquals (1 , PrototypeControllerAdvice .instanceCount .get ());
94
+ assertEquals (1 , RequestScopedControllerAdvice .instanceCount .get ());
73
95
74
- this .mockMvc .perform (get ("/test" ))//
96
+ this .mockMvc .perform (get ("/test" ). param ( "requestParam" , "bar" ) )//
75
97
.andExpect (status ().isOk ())//
76
- .andExpect (forwardedUrl ("singleton:1; request-scoped:1 " ));
98
+ .andExpect (forwardedUrl ("singleton:2;prototype:2; request-scoped:2;requestParam:bar " ));
77
99
78
- assertEquals (1 , SingletonControllerAdvice .counter .get ());
79
- assertEquals (1 , RequestScopedControllerAdvice .counter .get ());
100
+ // singleton @ControllerAdvice beans should not be instantiated again.
101
+ assertEquals (0 , SingletonControllerAdvice .instanceCount .get ());
102
+ // prototype and request-scoped @ControllerAdvice beans should be instantiated once per request.
103
+ assertEquals (2 , PrototypeControllerAdvice .instanceCount .get ());
104
+ assertEquals (2 , RequestScopedControllerAdvice .instanceCount .get ());
80
105
}
81
106
107
+ private static void resetCounters () {
108
+ SingletonControllerAdvice .invocationCount .set (0 );
109
+ SingletonControllerAdvice .instanceCount .set (0 );
110
+ PrototypeControllerAdvice .invocationCount .set (0 );
111
+ PrototypeControllerAdvice .instanceCount .set (0 );
112
+ RequestScopedControllerAdvice .invocationCount .set (0 );
113
+ RequestScopedControllerAdvice .instanceCount .set (0 );
114
+ }
115
+
116
+
82
117
@ Configuration
83
118
@ EnableWebMvc
84
119
static class Config {
@@ -93,6 +128,12 @@ SingletonControllerAdvice singletonControllerAdvice() {
93
128
return new SingletonControllerAdvice ();
94
129
}
95
130
131
+ @ Bean
132
+ @ Scope ("prototype" )
133
+ PrototypeControllerAdvice prototypeControllerAdvice () {
134
+ return new PrototypeControllerAdvice ();
135
+ }
136
+
96
137
@ Bean
97
138
@ RequestScope
98
139
RequestScopedControllerAdvice requestScopedControllerAdvice () {
@@ -103,22 +144,49 @@ RequestScopedControllerAdvice requestScopedControllerAdvice() {
103
144
@ ControllerAdvice
104
145
static class SingletonControllerAdvice {
105
146
106
- static final AtomicInteger counter = new AtomicInteger ();
147
+ static final AtomicInteger instanceCount = new AtomicInteger ();
148
+ static final AtomicInteger invocationCount = new AtomicInteger ();
149
+
150
+ {
151
+ instanceCount .incrementAndGet ();
152
+ }
107
153
108
154
@ ModelAttribute
109
155
void initModel (Model model ) {
110
- model .addAttribute ("singleton" , counter .incrementAndGet ());
156
+ model .addAttribute ("singleton" , invocationCount .incrementAndGet ());
111
157
}
112
158
}
113
159
114
160
@ ControllerAdvice
115
- static class RequestScopedControllerAdvice {
161
+ static class PrototypeControllerAdvice {
116
162
117
- static final AtomicInteger counter = new AtomicInteger ();
163
+ static final AtomicInteger instanceCount = new AtomicInteger ();
164
+ static final AtomicInteger invocationCount = new AtomicInteger ();
165
+
166
+ {
167
+ instanceCount .incrementAndGet ();
168
+ }
118
169
119
170
@ ModelAttribute
120
171
void initModel (Model model ) {
121
- model .addAttribute ("request-scoped" , counter .incrementAndGet ());
172
+ model .addAttribute ("prototype" , invocationCount .incrementAndGet ());
173
+ }
174
+ }
175
+
176
+ @ ControllerAdvice
177
+ static class RequestScopedControllerAdvice {
178
+
179
+ static final AtomicInteger instanceCount = new AtomicInteger ();
180
+ static final AtomicInteger invocationCount = new AtomicInteger ();
181
+
182
+ {
183
+ instanceCount .incrementAndGet ();
184
+ }
185
+
186
+ @ ModelAttribute
187
+ void initModel (@ RequestParam String requestParam , Model model ) {
188
+ model .addAttribute ("requestParam" , requestParam );
189
+ model .addAttribute ("request-scoped" , invocationCount .incrementAndGet ());
122
190
}
123
191
}
124
192
@@ -127,8 +195,11 @@ static class TestController {
127
195
128
196
@ GetMapping ("/test" )
129
197
String get (Model model ) {
130
- return "singleton:" + model .asMap ().get ("singleton" ) + ";request-scoped:"
131
- + model .asMap ().get ("request-scoped" );
198
+ Map <String , Object > map = model .asMap ();
199
+ return "singleton:" + map .get ("singleton" ) +
200
+ ";prototype:" + map .get ("prototype" ) +
201
+ ";request-scoped:" + map .get ("request-scoped" ) +
202
+ ";requestParam:" + map .get ("requestParam" );
132
203
}
133
204
}
134
205
0 commit comments