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 java.lang.reflect.AnnotatedElement; 020import java.lang.reflect.Member; 021import java.lang.reflect.Method; 022import java.util.HashSet; 023import java.util.Set; 024 025import org.springframework.beans.MutablePropertyValues; 026import org.springframework.beans.factory.config.BeanDefinition; 027import org.springframework.beans.factory.config.BeanDefinitionHolder; 028import org.springframework.beans.factory.config.ConstructorArgumentValues; 029import org.springframework.core.ResolvableType; 030import org.springframework.util.Assert; 031 032/** 033 * A root bean definition represents the merged bean definition that backs 034 * a specific bean in a Spring BeanFactory at runtime. It might have been created 035 * from multiple original bean definitions that inherit from each other, 036 * typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}. 037 * A root bean definition is essentially the 'unified' bean definition view at runtime. 038 * 039 * <p>Root bean definitions may also be used for registering individual bean definitions 040 * in the configuration phase. However, since Spring 2.5, the preferred way to register 041 * bean definitions programmatically is the {@link GenericBeanDefinition} class. 042 * GenericBeanDefinition has the advantage that it allows to dynamically define 043 * parent dependencies, not 'hard-coding' the role as a root bean definition. 044 * 045 * @author Rod Johnson 046 * @author Juergen Hoeller 047 * @see GenericBeanDefinition 048 * @see ChildBeanDefinition 049 */ 050@SuppressWarnings("serial") 051public class RootBeanDefinition extends AbstractBeanDefinition { 052 053 private BeanDefinitionHolder decoratedDefinition; 054 055 private AnnotatedElement qualifiedElement; 056 057 boolean allowCaching = true; 058 059 boolean isFactoryMethodUnique = false; 060 061 volatile ResolvableType targetType; 062 063 /** Package-visible field for caching the determined Class of a given bean definition */ 064 volatile Class<?> resolvedTargetType; 065 066 /** Package-visible field for caching the return type of a generically typed factory method */ 067 volatile ResolvableType factoryMethodReturnType; 068 069 /** Common lock for the four constructor fields below */ 070 final Object constructorArgumentLock = new Object(); 071 072 /** Package-visible field for caching the resolved constructor or factory method */ 073 Object resolvedConstructorOrFactoryMethod; 074 075 /** Package-visible field that marks the constructor arguments as resolved */ 076 boolean constructorArgumentsResolved = false; 077 078 /** Package-visible field for caching fully resolved constructor arguments */ 079 Object[] resolvedConstructorArguments; 080 081 /** Package-visible field for caching partly prepared constructor arguments */ 082 Object[] preparedConstructorArguments; 083 084 /** Common lock for the two post-processing fields below */ 085 final Object postProcessingLock = new Object(); 086 087 /** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */ 088 boolean postProcessed = false; 089 090 /** Package-visible field that indicates a before-instantiation post-processor having kicked in */ 091 volatile Boolean beforeInstantiationResolved; 092 093 private Set<Member> externallyManagedConfigMembers; 094 095 private Set<String> externallyManagedInitMethods; 096 097 private Set<String> externallyManagedDestroyMethods; 098 099 100 /** 101 * Create a new RootBeanDefinition, to be configured through its bean 102 * properties and configuration methods. 103 * @see #setBeanClass 104 * @see #setScope 105 * @see #setConstructorArgumentValues 106 * @see #setPropertyValues 107 */ 108 public RootBeanDefinition() { 109 super(); 110 } 111 112 /** 113 * Create a new RootBeanDefinition for a singleton. 114 * @param beanClass the class of the bean to instantiate 115 * @see #setBeanClass 116 */ 117 public RootBeanDefinition(Class<?> beanClass) { 118 super(); 119 setBeanClass(beanClass); 120 } 121 122 /** 123 * Create a new RootBeanDefinition for a singleton, 124 * using the given autowire mode. 125 * @param beanClass the class of the bean to instantiate 126 * @param autowireMode by name or type, using the constants in this interface 127 * @param dependencyCheck whether to perform a dependency check for objects 128 * (not applicable to autowiring a constructor, thus ignored there) 129 */ 130 public RootBeanDefinition(Class<?> beanClass, int autowireMode, boolean dependencyCheck) { 131 super(); 132 setBeanClass(beanClass); 133 setAutowireMode(autowireMode); 134 if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) { 135 setDependencyCheck(DEPENDENCY_CHECK_OBJECTS); 136 } 137 } 138 139 /** 140 * Create a new RootBeanDefinition for a singleton, 141 * providing constructor arguments and property values. 142 * @param beanClass the class of the bean to instantiate 143 * @param cargs the constructor argument values to apply 144 * @param pvs the property values to apply 145 */ 146 public RootBeanDefinition(Class<?> beanClass, ConstructorArgumentValues cargs, MutablePropertyValues pvs) { 147 super(cargs, pvs); 148 setBeanClass(beanClass); 149 } 150 151 /** 152 * Create a new RootBeanDefinition for a singleton, 153 * providing constructor arguments and property values. 154 * <p>Takes a bean class name to avoid eager loading of the bean class. 155 * @param beanClassName the name of the class to instantiate 156 */ 157 public RootBeanDefinition(String beanClassName) { 158 setBeanClassName(beanClassName); 159 } 160 161 /** 162 * Create a new RootBeanDefinition for a singleton, 163 * providing constructor arguments and property values. 164 * <p>Takes a bean class name to avoid eager loading of the bean class. 165 * @param beanClassName the name of the class to instantiate 166 * @param cargs the constructor argument values to apply 167 * @param pvs the property values to apply 168 */ 169 public RootBeanDefinition(String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) { 170 super(cargs, pvs); 171 setBeanClassName(beanClassName); 172 } 173 174 /** 175 * Create a new RootBeanDefinition as deep copy of the given 176 * bean definition. 177 * @param original the original bean definition to copy from 178 */ 179 public RootBeanDefinition(RootBeanDefinition original) { 180 super(original); 181 this.decoratedDefinition = original.decoratedDefinition; 182 this.qualifiedElement = original.qualifiedElement; 183 this.allowCaching = original.allowCaching; 184 this.isFactoryMethodUnique = original.isFactoryMethodUnique; 185 this.targetType = original.targetType; 186 } 187 188 /** 189 * Create a new RootBeanDefinition as deep copy of the given 190 * bean definition. 191 * @param original the original bean definition to copy from 192 */ 193 RootBeanDefinition(BeanDefinition original) { 194 super(original); 195 } 196 197 198 @Override 199 public String getParentName() { 200 return null; 201 } 202 203 @Override 204 public void setParentName(String parentName) { 205 if (parentName != null) { 206 throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference"); 207 } 208 } 209 210 /** 211 * Register a target definition that is being decorated by this bean definition. 212 */ 213 public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) { 214 this.decoratedDefinition = decoratedDefinition; 215 } 216 217 /** 218 * Return the target definition that is being decorated by this bean definition, if any. 219 */ 220 public BeanDefinitionHolder getDecoratedDefinition() { 221 return this.decoratedDefinition; 222 } 223 224 /** 225 * Specify the {@link AnnotatedElement} defining qualifiers, 226 * to be used instead of the target class or factory method. 227 * @since 4.3.3 228 * @see #setTargetType(ResolvableType) 229 * @see #getResolvedFactoryMethod() 230 */ 231 public void setQualifiedElement(AnnotatedElement qualifiedElement) { 232 this.qualifiedElement = qualifiedElement; 233 } 234 235 /** 236 * Return the {@link AnnotatedElement} defining qualifiers, if any. 237 * Otherwise, the factory method and target class will be checked. 238 * @since 4.3.3 239 */ 240 public AnnotatedElement getQualifiedElement() { 241 return this.qualifiedElement; 242 } 243 244 /** 245 * Specify a generics-containing target type of this bean definition, if known in advance. 246 * @since 4.3.3 247 */ 248 public void setTargetType(ResolvableType targetType) { 249 this.targetType = targetType; 250 } 251 252 /** 253 * Specify the target type of this bean definition, if known in advance. 254 * @since 3.2.2 255 */ 256 public void setTargetType(Class<?> targetType) { 257 this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null); 258 } 259 260 /** 261 * Return the target type of this bean definition, if known 262 * (either specified in advance or resolved on first instantiation). 263 * @since 3.2.2 264 */ 265 public Class<?> getTargetType() { 266 if (this.resolvedTargetType != null) { 267 return this.resolvedTargetType; 268 } 269 return (this.targetType != null ? this.targetType.resolve() : null); 270 } 271 272 /** 273 * Specify a factory method name that refers to a non-overloaded method. 274 */ 275 public void setUniqueFactoryMethodName(String name) { 276 Assert.hasText(name, "Factory method name must not be empty"); 277 setFactoryMethodName(name); 278 this.isFactoryMethodUnique = true; 279 } 280 281 /** 282 * Check whether the given candidate qualifies as a factory method. 283 */ 284 public boolean isFactoryMethod(Method candidate) { 285 return (candidate != null && candidate.getName().equals(getFactoryMethodName())); 286 } 287 288 /** 289 * Return the resolved factory method as a Java Method object, if available. 290 * @return the factory method, or {@code null} if not found or not resolved yet 291 */ 292 public Method getResolvedFactoryMethod() { 293 synchronized (this.constructorArgumentLock) { 294 Object candidate = this.resolvedConstructorOrFactoryMethod; 295 return (candidate instanceof Method ? (Method) candidate : null); 296 } 297 } 298 299 public void registerExternallyManagedConfigMember(Member configMember) { 300 synchronized (this.postProcessingLock) { 301 if (this.externallyManagedConfigMembers == null) { 302 this.externallyManagedConfigMembers = new HashSet<Member>(1); 303 } 304 this.externallyManagedConfigMembers.add(configMember); 305 } 306 } 307 308 public boolean isExternallyManagedConfigMember(Member configMember) { 309 synchronized (this.postProcessingLock) { 310 return (this.externallyManagedConfigMembers != null && 311 this.externallyManagedConfigMembers.contains(configMember)); 312 } 313 } 314 315 public void registerExternallyManagedInitMethod(String initMethod) { 316 synchronized (this.postProcessingLock) { 317 if (this.externallyManagedInitMethods == null) { 318 this.externallyManagedInitMethods = new HashSet<String>(1); 319 } 320 this.externallyManagedInitMethods.add(initMethod); 321 } 322 } 323 324 public boolean isExternallyManagedInitMethod(String initMethod) { 325 synchronized (this.postProcessingLock) { 326 return (this.externallyManagedInitMethods != null && 327 this.externallyManagedInitMethods.contains(initMethod)); 328 } 329 } 330 331 public void registerExternallyManagedDestroyMethod(String destroyMethod) { 332 synchronized (this.postProcessingLock) { 333 if (this.externallyManagedDestroyMethods == null) { 334 this.externallyManagedDestroyMethods = new HashSet<String>(1); 335 } 336 this.externallyManagedDestroyMethods.add(destroyMethod); 337 } 338 } 339 340 public boolean isExternallyManagedDestroyMethod(String destroyMethod) { 341 synchronized (this.postProcessingLock) { 342 return (this.externallyManagedDestroyMethods != null && 343 this.externallyManagedDestroyMethods.contains(destroyMethod)); 344 } 345 } 346 347 348 @Override 349 public RootBeanDefinition cloneBeanDefinition() { 350 return new RootBeanDefinition(this); 351 } 352 353 @Override 354 public boolean equals(Object other) { 355 return (this == other || (other instanceof RootBeanDefinition && super.equals(other))); 356 } 357 358 @Override 359 public String toString() { 360 return "Root bean: " + super.toString(); 361 } 362 363}