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 }