View Javadoc
1   /*
2    * Copyright 2002-2012 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.web.servlet.handler;
18  
19  import org.springframework.beans.BeansException;
20  import org.springframework.beans.factory.BeanFactoryUtils;
21  import org.springframework.context.ApplicationContextException;
22  import org.springframework.util.ObjectUtils;
23  
24  /**
25   * Abstract implementation of the {@link org.springframework.web.servlet.HandlerMapping}
26   * interface, detecting URL mappings for handler beans through introspection of all
27   * defined beans in the application context.
28   *
29   * @author Juergen Hoeller
30   * @since 2.5
31   * @see #determineUrlsForHandler
32   */
33  public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping {
34  
35  	private boolean detectHandlersInAncestorContexts = false;
36  
37  
38  	/**
39  	 * Set whether to detect handler beans in ancestor ApplicationContexts.
40  	 * <p>Default is "false": Only handler beans in the current ApplicationContext
41  	 * will be detected, i.e. only in the context that this HandlerMapping itself
42  	 * is defined in (typically the current DispatcherServlet's context).
43  	 * <p>Switch this flag on to detect handler beans in ancestor contexts
44  	 * (typically the Spring root WebApplicationContext) as well.
45  	 */
46  	public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) {
47  		this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts;
48  	}
49  
50  
51  	/**
52  	 * Calls the {@link #detectHandlers()} method in addition to the
53  	 * superclass's initialization.
54  	 */
55  	@Override
56  	public void initApplicationContext() throws ApplicationContextException {
57  		super.initApplicationContext();
58  		detectHandlers();
59  	}
60  
61  	/**
62  	 * Register all handlers found in the current ApplicationContext.
63  	 * <p>The actual URL determination for a handler is up to the concrete
64  	 * {@link #determineUrlsForHandler(String)} implementation. A bean for
65  	 * which no such URLs could be determined is simply not considered a handler.
66  	 * @throws org.springframework.beans.BeansException if the handler couldn't be registered
67  	 * @see #determineUrlsForHandler(String)
68  	 */
69  	protected void detectHandlers() throws BeansException {
70  		if (logger.isDebugEnabled()) {
71  			logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
72  		}
73  		String[] beanNames = (this.detectHandlersInAncestorContexts ?
74  				BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
75  				getApplicationContext().getBeanNamesForType(Object.class));
76  
77  		// Take any bean name that we can determine URLs for.
78  		for (String beanName : beanNames) {
79  			String[] urls = determineUrlsForHandler(beanName);
80  			if (!ObjectUtils.isEmpty(urls)) {
81  				// URL paths found: Let's consider it a handler.
82  				registerHandler(urls, beanName);
83  			}
84  			else {
85  				if (logger.isDebugEnabled()) {
86  					logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
87  				}
88  			}
89  		}
90  	}
91  
92  
93  	/**
94  	 * Determine the URLs for the given handler bean.
95  	 * @param beanName the name of the candidate bean
96  	 * @return the URLs determined for the bean,
97  	 * or {@code null} or an empty array if none
98  	 */
99  	protected abstract String[] determineUrlsForHandler(String beanName);
100 
101 }