001/* 002 * Copyright 2002-2019 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.Constructor; 021import java.lang.reflect.Executable; 022import java.lang.reflect.Member; 023import java.lang.reflect.Method; 024import java.util.HashSet; 025import java.util.Set; 026import java.util.function.Supplier; 027 028import org.springframework.beans.MutablePropertyValues; 029import org.springframework.beans.factory.config.BeanDefinition; 030import org.springframework.beans.factory.config.BeanDefinitionHolder; 031import org.springframework.beans.factory.config.ConstructorArgumentValues; 032import org.springframework.core.ResolvableType; 033import org.springframework.lang.Nullable; 034import org.springframework.util.Assert; 035 036/** 037 * A root bean definition represents the merged bean definition that backs 038 * a specific bean in a Spring BeanFactory at runtime. It might have been created 039 * from multiple original bean definitions that inherit from each other, 040 * typically registered as {@link GenericBeanDefinition GenericBeanDefinitions}. 041 * A root bean definition is essentially the 'unified' bean definition view at runtime. 042 * 043 * <p>Root bean definitions may also be used for registering individual bean definitions 044 * in the configuration phase. However, since Spring 2.5, the preferred way to register 045 * bean definitions programmatically is the {@link GenericBeanDefinition} class. 046 * GenericBeanDefinition has the advantage that it allows to dynamically define 047 * parent dependencies, not 'hard-coding' the role as a root bean definition. 048 * 049 * @author Rod Johnson 050 * @author Juergen Hoeller 051 * @see GenericBeanDefinition 052 * @see ChildBeanDefinition 053 */ 054@SuppressWarnings("serial") 055public class RootBeanDefinition extends AbstractBeanDefinition { 056 057 @Nullable 058 private BeanDefinitionHolder decoratedDefinition; 059 060 @Nullable 061 private AnnotatedElement qualifiedElement; 062 063 /** Determines if the definition needs to be re-merged. */ 064 volatile boolean stale; 065 066 boolean allowCaching = true; 067 068 boolean isFactoryMethodUnique = false; 069 070 @Nullable 071 volatile ResolvableType targetType; 072 073 /** Package-visible field for caching the determined Class of a given bean definition. */ 074 @Nullable 075 volatile Class<?> resolvedTargetType; 076 077 /** Package-visible field for caching if the bean is a factory bean. */ 078 @Nullable 079 volatile Boolean isFactoryBean; 080 081 /** Package-visible field for caching the return type of a generically typed factory method. */ 082 @Nullable 083 volatile ResolvableType factoryMethodReturnType; 084 085 /** Package-visible field for caching a unique factory method candidate for introspection. */ 086 @Nullable 087 volatile Method factoryMethodToIntrospect; 088 089 /** Common lock for the four constructor fields below. */ 090 final Object constructorArgumentLock = new Object(); 091 092 /** Package-visible field for caching the resolved constructor or factory method. */ 093 @Nullable 094 Executable resolvedConstructorOrFactoryMethod; 095 096 /** Package-visible field that marks the constructor arguments as resolved. */ 097 boolean constructorArgumentsResolved = false; 098 099 /** Package-visible field for caching fully resolved constructor arguments. */ 100 @Nullable 101 Object[] resolvedConstructorArguments; 102 103 /** Package-visible field for caching partly prepared constructor arguments. */ 104 @Nullable 105 Object[] preparedConstructorArguments; 106 107 /** Common lock for the two post-processing fields below. */ 108 final Object postProcessingLock = new Object(); 109 110 /** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied. */ 111 boolean postProcessed = false; 112 113 /** Package-visible field that indicates a before-instantiation post-processor having kicked in. */ 114 @Nullable 115 volatile Boolean beforeInstantiationResolved; 116 117 @Nullable 118 private Set<Member> externallyManagedConfigMembers; 119 120 @Nullable 121 private Set<String> externallyManagedInitMethods; 122 123 @Nullable 124 private Set<String> externallyManagedDestroyMethods; 125 126 127 /** 128 * Create a new RootBeanDefinition, to be configured through its bean 129 * properties and configuration methods. 130 * @see #setBeanClass 131 * @see #setScope 132 * @see #setConstructorArgumentValues 133 * @see #setPropertyValues 134 */ 135 public RootBeanDefinition() { 136 super(); 137 } 138 139 /** 140 * Create a new RootBeanDefinition for a singleton. 141 * @param beanClass the class of the bean to instantiate 142 * @see #setBeanClass 143 */ 144 public RootBeanDefinition(@Nullable Class<?> beanClass) { 145 super(); 146 setBeanClass(beanClass); 147 } 148 149 /** 150 * Create a new RootBeanDefinition for a singleton bean, constructing each instance 151 * through calling the given supplier (possibly a lambda or method reference). 152 * @param beanClass the class of the bean to instantiate 153 * @param instanceSupplier the supplier to construct a bean instance, 154 * as an alternative to a declaratively specified factory method 155 * @since 5.0 156 * @see #setInstanceSupplier 157 */ 158 public <T> RootBeanDefinition(@Nullable Class<T> beanClass, @Nullable Supplier<T> instanceSupplier) { 159 super(); 160 setBeanClass(beanClass); 161 setInstanceSupplier(instanceSupplier); 162 } 163 164 /** 165 * Create a new RootBeanDefinition for a scoped bean, constructing each instance 166 * through calling the given supplier (possibly a lambda or method reference). 167 * @param beanClass the class of the bean to instantiate 168 * @param scope the name of the corresponding scope 169 * @param instanceSupplier the supplier to construct a bean instance, 170 * as an alternative to a declaratively specified factory method 171 * @since 5.0 172 * @see #setInstanceSupplier 173 */ 174 public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) { 175 super(); 176 setBeanClass(beanClass); 177 setScope(scope); 178 setInstanceSupplier(instanceSupplier); 179 } 180 181 /** 182 * Create a new RootBeanDefinition for a singleton, 183 * using the given autowire mode. 184 * @param beanClass the class of the bean to instantiate 185 * @param autowireMode by name or type, using the constants in this interface 186 * @param dependencyCheck whether to perform a dependency check for objects 187 * (not applicable to autowiring a constructor, thus ignored there) 188 */ 189 public RootBeanDefinition(@Nullable Class<?> beanClass, int autowireMode, boolean dependencyCheck) { 190 super(); 191 setBeanClass(beanClass); 192 setAutowireMode(autowireMode); 193 if (dependencyCheck && getResolvedAutowireMode() != AUTOWIRE_CONSTRUCTOR) { 194 setDependencyCheck(DEPENDENCY_CHECK_OBJECTS); 195 } 196 } 197 198 /** 199 * Create a new RootBeanDefinition for a singleton, 200 * providing constructor arguments and property values. 201 * @param beanClass the class of the bean to instantiate 202 * @param cargs the constructor argument values to apply 203 * @param pvs the property values to apply 204 */ 205 public RootBeanDefinition(@Nullable Class<?> beanClass, @Nullable ConstructorArgumentValues cargs, 206 @Nullable MutablePropertyValues pvs) { 207 208 super(cargs, pvs); 209 setBeanClass(beanClass); 210 } 211 212 /** 213 * Create a new RootBeanDefinition for a singleton, 214 * providing constructor arguments and property values. 215 * <p>Takes a bean class name to avoid eager loading of the bean class. 216 * @param beanClassName the name of the class to instantiate 217 */ 218 public RootBeanDefinition(String beanClassName) { 219 setBeanClassName(beanClassName); 220 } 221 222 /** 223 * Create a new RootBeanDefinition for a singleton, 224 * providing constructor arguments and property values. 225 * <p>Takes a bean class name to avoid eager loading of the bean class. 226 * @param beanClassName the name of the class to instantiate 227 * @param cargs the constructor argument values to apply 228 * @param pvs the property values to apply 229 */ 230 public RootBeanDefinition(String beanClassName, ConstructorArgumentValues cargs, MutablePropertyValues pvs) { 231 super(cargs, pvs); 232 setBeanClassName(beanClassName); 233 } 234 235 /** 236 * Create a new RootBeanDefinition as deep copy of the given 237 * bean definition. 238 * @param original the original bean definition to copy from 239 */ 240 public RootBeanDefinition(RootBeanDefinition original) { 241 super(original); 242 this.decoratedDefinition = original.decoratedDefinition; 243 this.qualifiedElement = original.qualifiedElement; 244 this.allowCaching = original.allowCaching; 245 this.isFactoryMethodUnique = original.isFactoryMethodUnique; 246 this.targetType = original.targetType; 247 this.factoryMethodToIntrospect = original.factoryMethodToIntrospect; 248 } 249 250 /** 251 * Create a new RootBeanDefinition as deep copy of the given 252 * bean definition. 253 * @param original the original bean definition to copy from 254 */ 255 RootBeanDefinition(BeanDefinition original) { 256 super(original); 257 } 258 259 260 @Override 261 public String getParentName() { 262 return null; 263 } 264 265 @Override 266 public void setParentName(@Nullable String parentName) { 267 if (parentName != null) { 268 throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference"); 269 } 270 } 271 272 /** 273 * Register a target definition that is being decorated by this bean definition. 274 */ 275 public void setDecoratedDefinition(@Nullable BeanDefinitionHolder decoratedDefinition) { 276 this.decoratedDefinition = decoratedDefinition; 277 } 278 279 /** 280 * Return the target definition that is being decorated by this bean definition, if any. 281 */ 282 @Nullable 283 public BeanDefinitionHolder getDecoratedDefinition() { 284 return this.decoratedDefinition; 285 } 286 287 /** 288 * Specify the {@link AnnotatedElement} defining qualifiers, 289 * to be used instead of the target class or factory method. 290 * @since 4.3.3 291 * @see #setTargetType(ResolvableType) 292 * @see #getResolvedFactoryMethod() 293 */ 294 public void setQualifiedElement(@Nullable AnnotatedElement qualifiedElement) { 295 this.qualifiedElement = qualifiedElement; 296 } 297 298 /** 299 * Return the {@link AnnotatedElement} defining qualifiers, if any. 300 * Otherwise, the factory method and target class will be checked. 301 * @since 4.3.3 302 */ 303 @Nullable 304 public AnnotatedElement getQualifiedElement() { 305 return this.qualifiedElement; 306 } 307 308 /** 309 * Specify a generics-containing target type of this bean definition, if known in advance. 310 * @since 4.3.3 311 */ 312 public void setTargetType(ResolvableType targetType) { 313 this.targetType = targetType; 314 } 315 316 /** 317 * Specify the target type of this bean definition, if known in advance. 318 * @since 3.2.2 319 */ 320 public void setTargetType(@Nullable Class<?> targetType) { 321 this.targetType = (targetType != null ? ResolvableType.forClass(targetType) : null); 322 } 323 324 /** 325 * Return the target type of this bean definition, if known 326 * (either specified in advance or resolved on first instantiation). 327 * @since 3.2.2 328 */ 329 @Nullable 330 public Class<?> getTargetType() { 331 if (this.resolvedTargetType != null) { 332 return this.resolvedTargetType; 333 } 334 ResolvableType targetType = this.targetType; 335 return (targetType != null ? targetType.resolve() : null); 336 } 337 338 /** 339 * Return a {@link ResolvableType} for this bean definition, 340 * either from runtime-cached type information or from configuration-time 341 * {@link #setTargetType(ResolvableType)} or {@link #setBeanClass(Class)}, 342 * also considering resolved factory method definitions. 343 * @since 5.1 344 * @see #setTargetType(ResolvableType) 345 * @see #setBeanClass(Class) 346 * @see #setResolvedFactoryMethod(Method) 347 */ 348 @Override 349 public ResolvableType getResolvableType() { 350 ResolvableType targetType = this.targetType; 351 if (targetType != null) { 352 return targetType; 353 } 354 ResolvableType returnType = this.factoryMethodReturnType; 355 if (returnType != null) { 356 return returnType; 357 } 358 Method factoryMethod = this.factoryMethodToIntrospect; 359 if (factoryMethod != null) { 360 return ResolvableType.forMethodReturnType(factoryMethod); 361 } 362 return super.getResolvableType(); 363 } 364 365 /** 366 * Determine preferred constructors to use for default construction, if any. 367 * Constructor arguments will be autowired if necessary. 368 * @return one or more preferred constructors, or {@code null} if none 369 * (in which case the regular no-arg default constructor will be called) 370 * @since 5.1 371 */ 372 @Nullable 373 public Constructor<?>[] getPreferredConstructors() { 374 return null; 375 } 376 377 /** 378 * Specify a factory method name that refers to a non-overloaded method. 379 */ 380 public void setUniqueFactoryMethodName(String name) { 381 Assert.hasText(name, "Factory method name must not be empty"); 382 setFactoryMethodName(name); 383 this.isFactoryMethodUnique = true; 384 } 385 386 /** 387 * Specify a factory method name that refers to an overloaded method. 388 * @since 5.2 389 */ 390 public void setNonUniqueFactoryMethodName(String name) { 391 Assert.hasText(name, "Factory method name must not be empty"); 392 setFactoryMethodName(name); 393 this.isFactoryMethodUnique = false; 394 } 395 396 /** 397 * Check whether the given candidate qualifies as a factory method. 398 */ 399 public boolean isFactoryMethod(Method candidate) { 400 return candidate.getName().equals(getFactoryMethodName()); 401 } 402 403 /** 404 * Set a resolved Java Method for the factory method on this bean definition. 405 * @param method the resolved factory method, or {@code null} to reset it 406 * @since 5.2 407 */ 408 public void setResolvedFactoryMethod(@Nullable Method method) { 409 this.factoryMethodToIntrospect = method; 410 } 411 412 /** 413 * Return the resolved factory method as a Java Method object, if available. 414 * @return the factory method, or {@code null} if not found or not resolved yet 415 */ 416 @Nullable 417 public Method getResolvedFactoryMethod() { 418 return this.factoryMethodToIntrospect; 419 } 420 421 public void registerExternallyManagedConfigMember(Member configMember) { 422 synchronized (this.postProcessingLock) { 423 if (this.externallyManagedConfigMembers == null) { 424 this.externallyManagedConfigMembers = new HashSet<>(1); 425 } 426 this.externallyManagedConfigMembers.add(configMember); 427 } 428 } 429 430 public boolean isExternallyManagedConfigMember(Member configMember) { 431 synchronized (this.postProcessingLock) { 432 return (this.externallyManagedConfigMembers != null && 433 this.externallyManagedConfigMembers.contains(configMember)); 434 } 435 } 436 437 public void registerExternallyManagedInitMethod(String initMethod) { 438 synchronized (this.postProcessingLock) { 439 if (this.externallyManagedInitMethods == null) { 440 this.externallyManagedInitMethods = new HashSet<>(1); 441 } 442 this.externallyManagedInitMethods.add(initMethod); 443 } 444 } 445 446 public boolean isExternallyManagedInitMethod(String initMethod) { 447 synchronized (this.postProcessingLock) { 448 return (this.externallyManagedInitMethods != null && 449 this.externallyManagedInitMethods.contains(initMethod)); 450 } 451 } 452 453 public void registerExternallyManagedDestroyMethod(String destroyMethod) { 454 synchronized (this.postProcessingLock) { 455 if (this.externallyManagedDestroyMethods == null) { 456 this.externallyManagedDestroyMethods = new HashSet<>(1); 457 } 458 this.externallyManagedDestroyMethods.add(destroyMethod); 459 } 460 } 461 462 public boolean isExternallyManagedDestroyMethod(String destroyMethod) { 463 synchronized (this.postProcessingLock) { 464 return (this.externallyManagedDestroyMethods != null && 465 this.externallyManagedDestroyMethods.contains(destroyMethod)); 466 } 467 } 468 469 470 @Override 471 public RootBeanDefinition cloneBeanDefinition() { 472 return new RootBeanDefinition(this); 473 } 474 475 @Override 476 public boolean equals(@Nullable Object other) { 477 return (this == other || (other instanceof RootBeanDefinition && super.equals(other))); 478 } 479 480 @Override 481 public String toString() { 482 return "Root bean: " + super.toString(); 483 } 484 485}