Skip to content

Commit 14161d1

Browse files
committed
Protected applyLifecycleMethods in UrlBasedViewResolver
Issue: SPR-15219
1 parent 6320976 commit 14161d1

File tree

3 files changed

+81
-45
lines changed

3 files changed

+81
-45
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/result/view/UrlBasedViewResolver.java

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.springframework.beans.BeanUtils;
2525
import org.springframework.beans.factory.InitializingBean;
2626
import org.springframework.context.ApplicationContext;
27+
import org.springframework.context.ApplicationContextAware;
2728
import org.springframework.lang.Nullable;
2829
import org.springframework.util.Assert;
2930
import org.springframework.util.PatternMatchUtils;
@@ -57,9 +58,11 @@
5758
*
5859
* @author Rossen Stoyanchev
5960
* @author Sebastien Deleuze
61+
* @author Juergen Hoeller
6062
* @since 5.0
6163
*/
62-
public class UrlBasedViewResolver extends ViewResolverSupport implements ViewResolver, InitializingBean {
64+
public class UrlBasedViewResolver extends ViewResolverSupport
65+
implements ViewResolver, ApplicationContextAware, InitializingBean {
6366

6467
/**
6568
* Prefix for special view names that specify a redirect URL (usually
@@ -82,11 +85,13 @@ public class UrlBasedViewResolver extends ViewResolverSupport implements ViewRes
8285

8386
private String requestContextAttribute;
8487

88+
private ApplicationContext applicationContext;
89+
8590

8691
/**
87-
* Set the view class to instantiate through {@link #createUrlBasedView(String)}.
92+
* Set the view class to instantiate through {@link #createView(String)}.
8893
* @param viewClass a class that is assignable to the required view class
89-
* which by default is AbstractUrlBasedView.
94+
* which by default is AbstractUrlBasedView
9095
*/
9196
public void setViewClass(Class<?> viewClass) {
9297
if (!requiredViewClass().isAssignableFrom(viewClass)) {
@@ -170,7 +175,7 @@ public void setRedirectViewProvider(Function<String, RedirectView> redirectViewP
170175
}
171176

172177
/**
173-
* Set the name of the RequestContext attribute for all views.
178+
* Set the name of the {@link RequestContext} attribute for all views.
174179
* @param requestContextAttribute name of the RequestContext attribute
175180
* @see AbstractView#setRequestContextAttribute
176181
*/
@@ -179,13 +184,35 @@ public void setRequestContextAttribute(String requestContextAttribute) {
179184
}
180185

181186
/**
182-
* Return the name of the RequestContext attribute for all views, if any.
187+
* Return the name of the @link RequestContext} attribute for all views, if any.
183188
*/
184189
@Nullable
185190
protected String getRequestContextAttribute() {
186191
return this.requestContextAttribute;
187192
}
188193

194+
/**
195+
* Accept the containing {@code ApplicationContext}, if any.
196+
* <p>To be used for the initialization of newly created {@link View} instances,
197+
* applying lifecycle callbacks and providing access to the containing environment.
198+
* @see #setViewClass
199+
* @see #createView
200+
* @see #applyLifecycleMethods
201+
*/
202+
@Override
203+
public void setApplicationContext(ApplicationContext applicationContext) {
204+
this.applicationContext = applicationContext;
205+
}
206+
207+
/**
208+
* Return the containing {@code ApplicationContext}, if any.
209+
* @see #setApplicationContext
210+
*/
211+
@Nullable
212+
public ApplicationContext getApplicationContext() {
213+
return this.applicationContext;
214+
}
215+
189216

190217
@Override
191218
public void afterPropertiesSet() throws Exception {
@@ -207,7 +234,7 @@ public Mono<View> resolveViewName(String viewName, Locale locale) {
207234
urlBasedView = this.redirectViewProvider.apply(redirectUrl);
208235
}
209236
else {
210-
urlBasedView = createUrlBasedView(viewName);
237+
urlBasedView = createView(viewName);
211238
}
212239

213240
View view = applyLifecycleMethods(viewName, urlBasedView);
@@ -220,10 +247,9 @@ public Mono<View> resolveViewName(String viewName, Locale locale) {
220247
}
221248

222249
/**
223-
* Indicates whether or not this {@link ViewResolver} can handle the
224-
* supplied view name. If not, an empty result is returned. The default
225-
* implementation checks against the configured {@link #setViewNames
226-
* view names}.
250+
* Indicates whether or not this {@link ViewResolver} can handle the supplied
251+
* view name. If not, an empty result is returned. The default implementation
252+
* checks against the configured {@link #setViewNames view names}.
227253
* @param viewName the name of the view to retrieve
228254
* @param locale the Locale to retrieve the view for
229255
* @return whether this resolver applies to the specified view
@@ -238,15 +264,14 @@ protected boolean canHandle(String viewName, Locale locale) {
238264
* Creates a new View instance of the specified view class and configures it.
239265
* Does <i>not</i> perform any lookup for pre-defined View instances.
240266
* <p>Spring lifecycle methods as defined by the bean container do not have to
241-
* be called here; those will be applied by the {@code loadView} method
242-
* after this method returns.
243-
* <p>Subclasses will typically call {@code super.buildView(viewName)}
244-
* first, before setting further properties themselves. {@code loadView}
245-
* will then apply Spring lifecycle methods at the end of this process.
267+
* be called here: They will be automatically applied afterwards, provided
268+
* that an {@link #setApplicationContext ApplicationContext} is available.
246269
* @param viewName the name of the view to build
247270
* @return the View instance
271+
* @see #getViewClass()
272+
* @see #applyLifecycleMethods
248273
*/
249-
protected AbstractUrlBasedView createUrlBasedView(String viewName) {
274+
protected AbstractUrlBasedView createView(String viewName) {
250275
Class<?> viewClass = getViewClass();
251276
Assert.state(viewClass != null, "No view class");
252277

@@ -259,7 +284,19 @@ protected AbstractUrlBasedView createUrlBasedView(String viewName) {
259284
return view;
260285
}
261286

262-
private View applyLifecycleMethods(String viewName, AbstractView view) {
287+
/**
288+
* Apply the containing {@link ApplicationContext}'s lifecycle methods
289+
* to the given {@link View} instance, if such a context is available.
290+
* @param viewName the name of the view
291+
* @param view the freshly created View instance, pre-configured with
292+
* {@link AbstractUrlBasedView}'s properties
293+
* @return the {@link View} instance to use (either the original one
294+
* or a decorated variant)
295+
* @see #getApplicationContext()
296+
* @see ApplicationContext#getAutowireCapableBeanFactory()
297+
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#initializeBean
298+
*/
299+
protected View applyLifecycleMethods(String viewName, AbstractUrlBasedView view) {
263300
ApplicationContext context = getApplicationContext();
264301
if (context != null) {
265302
Object initialized = context.getAutowireCapableBeanFactory().initializeBean(view, viewName);

spring-webflux/src/main/java/org/springframework/web/reactive/result/view/ViewResolverSupport.java

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
import java.util.ArrayList;
2222
import java.util.List;
2323

24-
import org.springframework.context.ApplicationContext;
25-
import org.springframework.context.ApplicationContextAware;
2624
import org.springframework.core.Ordered;
2725
import org.springframework.http.MediaType;
2826
import org.springframework.lang.Nullable;
@@ -32,9 +30,10 @@
3230
* Base class for {@code ViewResolver} implementations with shared properties.
3331
*
3432
* @author Rossen Stoyanchev
33+
* @author Juergen Hoeller
3534
* @since 5.0
3635
*/
37-
public abstract class ViewResolverSupport implements ApplicationContextAware, Ordered {
36+
public abstract class ViewResolverSupport implements Ordered {
3837

3938
public static final MediaType DEFAULT_CONTENT_TYPE = MediaType.parseMediaType("text/html;charset=UTF-8");
4039

@@ -43,8 +42,6 @@ public abstract class ViewResolverSupport implements ApplicationContextAware, Or
4342

4443
private Charset defaultCharset = StandardCharsets.UTF_8;
4544

46-
private ApplicationContext applicationContext;
47-
4845
private int order = Integer.MAX_VALUE;
4946

5047

@@ -91,19 +88,8 @@ public Charset getDefaultCharset() {
9188
}
9289

9390

94-
@Override
95-
public void setApplicationContext(ApplicationContext applicationContext) {
96-
this.applicationContext = applicationContext;
97-
}
98-
99-
@Nullable
100-
public ApplicationContext getApplicationContext() {
101-
return this.applicationContext;
102-
}
103-
10491
/**
105-
* Set the order in which this {@link ViewResolver}
106-
* is evaluated.
92+
* Set the order in which this {@link ViewResolver} is evaluated.
10793
*/
10894
public void setOrder(int order) {
10995
this.order = order;

spring-webmvc/src/main/java/org/springframework/web/servlet/view/UrlBasedViewResolver.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -516,17 +516,6 @@ protected View loadView(String viewName, Locale locale) throws Exception {
516516
return (view.checkResource(locale) ? result : null);
517517
}
518518

519-
private View applyLifecycleMethods(String viewName, AbstractView view) {
520-
ApplicationContext context = getApplicationContext();
521-
if (context != null) {
522-
Object initialized = context.getAutowireCapableBeanFactory().initializeBean(view, viewName);
523-
if (initialized instanceof View) {
524-
return (View) initialized;
525-
}
526-
}
527-
return view;
528-
}
529-
530519
/**
531520
* Creates a new View instance of the specified view class and configures it.
532521
* Does <i>not</i> perform any lookup for pre-defined View instances.
@@ -572,4 +561,28 @@ protected AbstractUrlBasedView buildView(String viewName) throws Exception {
572561
return view;
573562
}
574563

564+
/**
565+
* Apply the containing {@link ApplicationContext}'s lifecycle methods
566+
* to the given {@link View} instance, if such a context is available.
567+
* @param viewName the name of the view
568+
* @param view the freshly created View instance, pre-configured with
569+
* {@link AbstractUrlBasedView}'s properties
570+
* @return the {@link View} instance to use (either the original one
571+
* or a decorated variant)
572+
* @since 5.0
573+
* @see #getApplicationContext()
574+
* @see ApplicationContext#getAutowireCapableBeanFactory()
575+
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#initializeBean
576+
*/
577+
protected View applyLifecycleMethods(String viewName, AbstractUrlBasedView view) {
578+
ApplicationContext context = getApplicationContext();
579+
if (context != null) {
580+
Object initialized = context.getAutowireCapableBeanFactory().initializeBean(view, viewName);
581+
if (initialized instanceof View) {
582+
return (View) initialized;
583+
}
584+
}
585+
return view;
586+
}
587+
575588
}

0 commit comments

Comments
 (0)