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