001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.beans.factory.xml; 018 019import org.w3c.dom.Element; 020 021import org.springframework.beans.factory.support.AbstractBeanDefinition; 022import org.springframework.beans.factory.support.BeanDefinitionBuilder; 023 024/** 025 * Base class for those {@link BeanDefinitionParser} implementations that 026 * need to parse and define just a <i>single</i> {@code BeanDefinition}. 027 * 028 * <p>Extend this parser class when you want to create a single bean definition 029 * from an arbitrarily complex XML element. You may wish to consider extending 030 * the {@link AbstractSimpleBeanDefinitionParser} when you want to create a 031 * single bean definition from a relatively simple custom XML element. 032 * 033 * <p>The resulting {@code BeanDefinition} will be automatically registered 034 * with the {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}. 035 * Your job simply is to {@link #doParse parse} the custom XML {@link Element} 036 * into a single {@code BeanDefinition}. 037 * 038 * @author Rob Harrop 039 * @author Juergen Hoeller 040 * @author Rick Evans 041 * @since 2.0 042 * @see #getBeanClass 043 * @see #getBeanClassName 044 * @see #doParse 045 */ 046public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser { 047 048 /** 049 * Creates a {@link BeanDefinitionBuilder} instance for the 050 * {@link #getBeanClass bean Class} and passes it to the 051 * {@link #doParse} strategy method. 052 * @param element the element that is to be parsed into a single BeanDefinition 053 * @param parserContext the object encapsulating the current state of the parsing process 054 * @return the BeanDefinition resulting from the parsing of the supplied {@link Element} 055 * @throws IllegalStateException if the bean {@link Class} returned from 056 * {@link #getBeanClass(org.w3c.dom.Element)} is {@code null} 057 * @see #doParse 058 */ 059 @Override 060 protected final AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { 061 BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(); 062 String parentName = getParentName(element); 063 if (parentName != null) { 064 builder.getRawBeanDefinition().setParentName(parentName); 065 } 066 Class<?> beanClass = getBeanClass(element); 067 if (beanClass != null) { 068 builder.getRawBeanDefinition().setBeanClass(beanClass); 069 } 070 else { 071 String beanClassName = getBeanClassName(element); 072 if (beanClassName != null) { 073 builder.getRawBeanDefinition().setBeanClassName(beanClassName); 074 } 075 } 076 builder.getRawBeanDefinition().setSource(parserContext.extractSource(element)); 077 if (parserContext.isNested()) { 078 // Inner bean definition must receive same scope as containing bean. 079 builder.setScope(parserContext.getContainingBeanDefinition().getScope()); 080 } 081 if (parserContext.isDefaultLazyInit()) { 082 // Default-lazy-init applies to custom bean definitions as well. 083 builder.setLazyInit(true); 084 } 085 doParse(element, parserContext, builder); 086 return builder.getBeanDefinition(); 087 } 088 089 /** 090 * Determine the name for the parent of the currently parsed bean, 091 * in case of the current bean being defined as a child bean. 092 * <p>The default implementation returns {@code null}, 093 * indicating a root bean definition. 094 * @param element the {@code Element} that is being parsed 095 * @return the name of the parent bean for the currently parsed bean, 096 * or {@code null} if none 097 */ 098 protected String getParentName(Element element) { 099 return null; 100 } 101 102 /** 103 * Determine the bean class corresponding to the supplied {@link Element}. 104 * <p>Note that, for application classes, it is generally preferable to 105 * override {@link #getBeanClassName} instead, in order to avoid a direct 106 * dependence on the bean implementation class. The BeanDefinitionParser 107 * and its NamespaceHandler can be used within an IDE plugin then, even 108 * if the application classes are not available on the plugin's classpath. 109 * @param element the {@code Element} that is being parsed 110 * @return the {@link Class} of the bean that is being defined via parsing 111 * the supplied {@code Element}, or {@code null} if none 112 * @see #getBeanClassName 113 */ 114 protected Class<?> getBeanClass(Element element) { 115 return null; 116 } 117 118 /** 119 * Determine the bean class name corresponding to the supplied {@link Element}. 120 * @param element the {@code Element} that is being parsed 121 * @return the class name of the bean that is being defined via parsing 122 * the supplied {@code Element}, or {@code null} if none 123 * @see #getBeanClass 124 */ 125 protected String getBeanClassName(Element element) { 126 return null; 127 } 128 129 /** 130 * Parse the supplied {@link Element} and populate the supplied 131 * {@link BeanDefinitionBuilder} as required. 132 * <p>The default implementation delegates to the {@code doParse} 133 * version without ParserContext argument. 134 * @param element the XML element being parsed 135 * @param parserContext the object encapsulating the current state of the parsing process 136 * @param builder used to define the {@code BeanDefinition} 137 * @see #doParse(Element, BeanDefinitionBuilder) 138 */ 139 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { 140 doParse(element, builder); 141 } 142 143 /** 144 * Parse the supplied {@link Element} and populate the supplied 145 * {@link BeanDefinitionBuilder} as required. 146 * <p>The default implementation does nothing. 147 * @param element the XML element being parsed 148 * @param builder used to define the {@code BeanDefinition} 149 */ 150 protected void doParse(Element element, BeanDefinitionBuilder builder) { 151 } 152 153}