001/* 002 * Copyright 2002-2016 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.support; 018 019import org.springframework.beans.MutablePropertyValues; 020import org.springframework.beans.factory.config.ConstructorArgumentValues; 021import org.springframework.util.ObjectUtils; 022 023/** 024 * Bean definition for beans which inherit settings from their parent. 025 * Child bean definitions have a fixed dependency on a parent bean definition. 026 * 027 * <p>A child bean definition will inherit constructor argument values, 028 * property values and method overrides from the parent, with the option 029 * to add new values. If init method, destroy method and/or static factory 030 * method are specified, they will override the corresponding parent settings. 031 * The remaining settings will <i>always</i> be taken from the child definition: 032 * depends on, autowire mode, dependency check, singleton, lazy init. 033 * 034 * <p><b>NOTE:</b> Since Spring 2.5, the preferred way to register bean 035 * definitions programmatically is the {@link GenericBeanDefinition} class, 036 * which allows to dynamically define parent dependencies through the 037 * {@link GenericBeanDefinition#setParentName} method. This effectively 038 * supersedes the ChildBeanDefinition class for most use cases. 039 * 040 * @author Rod Johnson 041 * @author Juergen Hoeller 042 * @see GenericBeanDefinition 043 * @see RootBeanDefinition 044 */ 045@SuppressWarnings("serial") 046public class ChildBeanDefinition extends AbstractBeanDefinition { 047 048 private String parentName; 049 050 051 /** 052 * Create a new ChildBeanDefinition for the given parent, to be 053 * configured through its bean properties and configuration methods. 054 * @param parentName the name of the parent bean 055 * @see #setBeanClass 056 * @see #setScope 057 * @see #setConstructorArgumentValues 058 * @see #setPropertyValues 059 */ 060 public ChildBeanDefinition(String parentName) { 061 super(); 062 this.parentName = parentName; 063 } 064 065 /** 066 * Create a new ChildBeanDefinition for the given parent. 067 * @param parentName the name of the parent bean 068 * @param pvs the additional property values of the child 069 */ 070 public ChildBeanDefinition(String parentName, MutablePropertyValues pvs) { 071 super(null, pvs); 072 this.parentName = parentName; 073 } 074 075 /** 076 * Create a new ChildBeanDefinition for the given parent. 077 * @param parentName the name of the parent bean 078 * @param cargs the constructor argument values to apply 079 * @param pvs the additional property values of the child 080 */ 081 public ChildBeanDefinition( 082 String parentName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) { 083 084 super(cargs, pvs); 085 this.parentName = parentName; 086 } 087 088 /** 089 * Create a new ChildBeanDefinition for the given parent, 090 * providing constructor arguments and property values. 091 * @param parentName the name of the parent bean 092 * @param beanClass the class of the bean to instantiate 093 * @param cargs the constructor argument values to apply 094 * @param pvs the property values to apply 095 */ 096 public ChildBeanDefinition( 097 String parentName, Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) { 098 099 super(cargs, pvs); 100 this.parentName = parentName; 101 setBeanClass(beanClass); 102 } 103 104 /** 105 * Create a new ChildBeanDefinition for the given parent, 106 * providing constructor arguments and property values. 107 * Takes a bean class name to avoid eager loading of the bean class. 108 * @param parentName the name of the parent bean 109 * @param beanClassName the name of the class to instantiate 110 * @param cargs the constructor argument values to apply 111 * @param pvs the property values to apply 112 */ 113 public ChildBeanDefinition( 114 String parentName, String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) { 115 116 super(cargs, pvs); 117 this.parentName = parentName; 118 setBeanClassName(beanClassName); 119 } 120 121 /** 122 * Create a new ChildBeanDefinition as deep copy of the given 123 * bean definition. 124 * @param original the original bean definition to copy from 125 */ 126 public ChildBeanDefinition(ChildBeanDefinition original) { 127 super(original); 128 } 129 130 131 @Override 132 public void setParentName(String parentName) { 133 this.parentName = parentName; 134 } 135 136 @Override 137 public String getParentName() { 138 return this.parentName; 139 } 140 141 @Override 142 public void validate() throws BeanDefinitionValidationException { 143 super.validate(); 144 if (this.parentName == null) { 145 throw new BeanDefinitionValidationException("'parentName' must be set in ChildBeanDefinition"); 146 } 147 } 148 149 150 @Override 151 public AbstractBeanDefinition cloneBeanDefinition() { 152 return new ChildBeanDefinition(this); 153 } 154 155 @Override 156 public boolean equals(Object other) { 157 if (this == other) { 158 return true; 159 } 160 if (!(other instanceof ChildBeanDefinition)) { 161 return false; 162 } 163 ChildBeanDefinition that = (ChildBeanDefinition) other; 164 return (ObjectUtils.nullSafeEquals(this.parentName, that.parentName) && super.equals(other)); 165 } 166 167 @Override 168 public int hashCode() { 169 return ObjectUtils.nullSafeHashCode(this.parentName) * 29 + super.hashCode(); 170 } 171 172 @Override 173 public String toString() { 174 return "Child bean with parent '" + this.parentName + "': " + super.toString(); 175 } 176 177}