001/* 002 * Copyright 2002-2020 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.beans.PropertyEditor; 020import java.security.AccessControlContext; 021import java.security.AccessController; 022import java.security.PrivilegedAction; 023import java.security.PrivilegedActionException; 024import java.security.PrivilegedExceptionAction; 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.HashMap; 029import java.util.HashSet; 030import java.util.LinkedHashMap; 031import java.util.LinkedHashSet; 032import java.util.List; 033import java.util.Map; 034import java.util.Set; 035import java.util.concurrent.ConcurrentHashMap; 036import java.util.concurrent.CopyOnWriteArrayList; 037 038import org.springframework.beans.BeanUtils; 039import org.springframework.beans.BeanWrapper; 040import org.springframework.beans.BeansException; 041import org.springframework.beans.PropertyEditorRegistrar; 042import org.springframework.beans.PropertyEditorRegistry; 043import org.springframework.beans.PropertyEditorRegistrySupport; 044import org.springframework.beans.SimpleTypeConverter; 045import org.springframework.beans.TypeConverter; 046import org.springframework.beans.TypeMismatchException; 047import org.springframework.beans.factory.BeanCreationException; 048import org.springframework.beans.factory.BeanCurrentlyInCreationException; 049import org.springframework.beans.factory.BeanDefinitionStoreException; 050import org.springframework.beans.factory.BeanFactory; 051import org.springframework.beans.factory.BeanFactoryUtils; 052import org.springframework.beans.factory.BeanIsAbstractException; 053import org.springframework.beans.factory.BeanIsNotAFactoryException; 054import org.springframework.beans.factory.BeanNotOfRequiredTypeException; 055import org.springframework.beans.factory.CannotLoadBeanClassException; 056import org.springframework.beans.factory.FactoryBean; 057import org.springframework.beans.factory.NoSuchBeanDefinitionException; 058import org.springframework.beans.factory.SmartFactoryBean; 059import org.springframework.beans.factory.config.BeanDefinition; 060import org.springframework.beans.factory.config.BeanDefinitionHolder; 061import org.springframework.beans.factory.config.BeanExpressionContext; 062import org.springframework.beans.factory.config.BeanExpressionResolver; 063import org.springframework.beans.factory.config.BeanPostProcessor; 064import org.springframework.beans.factory.config.ConfigurableBeanFactory; 065import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; 066import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; 067import org.springframework.beans.factory.config.Scope; 068import org.springframework.core.AttributeAccessor; 069import org.springframework.core.DecoratingClassLoader; 070import org.springframework.core.NamedThreadLocal; 071import org.springframework.core.ResolvableType; 072import org.springframework.core.convert.ConversionService; 073import org.springframework.core.log.LogMessage; 074import org.springframework.lang.Nullable; 075import org.springframework.util.Assert; 076import org.springframework.util.ClassUtils; 077import org.springframework.util.ObjectUtils; 078import org.springframework.util.StringUtils; 079import org.springframework.util.StringValueResolver; 080 081/** 082 * Abstract base class for {@link org.springframework.beans.factory.BeanFactory} 083 * implementations, providing the full capabilities of the 084 * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI. 085 * Does <i>not</i> assume a listable bean factory: can therefore also be used 086 * as base class for bean factory implementations which obtain bean definitions 087 * from some backend resource (where bean definition access is an expensive operation). 088 * 089 * <p>This class provides a singleton cache (through its base class 090 * {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry}, 091 * singleton/prototype determination, {@link org.springframework.beans.factory.FactoryBean} 092 * handling, aliases, bean definition merging for child bean definitions, 093 * and bean destruction ({@link org.springframework.beans.factory.DisposableBean} 094 * interface, custom destroy methods). Furthermore, it can manage a bean factory 095 * hierarchy (delegating to the parent in case of an unknown bean), through implementing 096 * the {@link org.springframework.beans.factory.HierarchicalBeanFactory} interface. 097 * 098 * <p>The main template methods to be implemented by subclasses are 099 * {@link #getBeanDefinition} and {@link #createBean}, retrieving a bean definition 100 * for a given bean name and creating a bean instance for a given bean definition, 101 * respectively. Default implementations of those operations can be found in 102 * {@link DefaultListableBeanFactory} and {@link AbstractAutowireCapableBeanFactory}. 103 * 104 * @author Rod Johnson 105 * @author Juergen Hoeller 106 * @author Costin Leau 107 * @author Chris Beams 108 * @author Phillip Webb 109 * @since 15 April 2001 110 * @see #getBeanDefinition 111 * @see #createBean 112 * @see AbstractAutowireCapableBeanFactory#createBean 113 * @see DefaultListableBeanFactory#getBeanDefinition 114 */ 115public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { 116 117 /** Parent bean factory, for bean inheritance support. */ 118 @Nullable 119 private BeanFactory parentBeanFactory; 120 121 /** ClassLoader to resolve bean class names with, if necessary. */ 122 @Nullable 123 private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); 124 125 /** ClassLoader to temporarily resolve bean class names with, if necessary. */ 126 @Nullable 127 private ClassLoader tempClassLoader; 128 129 /** Whether to cache bean metadata or rather reobtain it for every access. */ 130 private boolean cacheBeanMetadata = true; 131 132 /** Resolution strategy for expressions in bean definition values. */ 133 @Nullable 134 private BeanExpressionResolver beanExpressionResolver; 135 136 /** Spring ConversionService to use instead of PropertyEditors. */ 137 @Nullable 138 private ConversionService conversionService; 139 140 /** Custom PropertyEditorRegistrars to apply to the beans of this factory. */ 141 private final Set<PropertyEditorRegistrar> propertyEditorRegistrars = new LinkedHashSet<>(4); 142 143 /** Custom PropertyEditors to apply to the beans of this factory. */ 144 private final Map<Class<?>, Class<? extends PropertyEditor>> customEditors = new HashMap<>(4); 145 146 /** A custom TypeConverter to use, overriding the default PropertyEditor mechanism. */ 147 @Nullable 148 private TypeConverter typeConverter; 149 150 /** String resolvers to apply e.g. to annotation attribute values. */ 151 private final List<StringValueResolver> embeddedValueResolvers = new CopyOnWriteArrayList<>(); 152 153 /** BeanPostProcessors to apply. */ 154 private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>(); 155 156 /** Indicates whether any InstantiationAwareBeanPostProcessors have been registered. */ 157 private volatile boolean hasInstantiationAwareBeanPostProcessors; 158 159 /** Indicates whether any DestructionAwareBeanPostProcessors have been registered. */ 160 private volatile boolean hasDestructionAwareBeanPostProcessors; 161 162 /** Map from scope identifier String to corresponding Scope. */ 163 private final Map<String, Scope> scopes = new LinkedHashMap<>(8); 164 165 /** Security context used when running with a SecurityManager. */ 166 @Nullable 167 private SecurityContextProvider securityContextProvider; 168 169 /** Map from bean name to merged RootBeanDefinition. */ 170 private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256); 171 172 /** Names of beans that have already been created at least once. */ 173 private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); 174 175 /** Names of beans that are currently in creation. */ 176 private final ThreadLocal<Object> prototypesCurrentlyInCreation = 177 new NamedThreadLocal<>("Prototype beans currently in creation"); 178 179 180 /** 181 * Create a new AbstractBeanFactory. 182 */ 183 public AbstractBeanFactory() { 184 } 185 186 /** 187 * Create a new AbstractBeanFactory with the given parent. 188 * @param parentBeanFactory parent bean factory, or {@code null} if none 189 * @see #getBean 190 */ 191 public AbstractBeanFactory(@Nullable BeanFactory parentBeanFactory) { 192 this.parentBeanFactory = parentBeanFactory; 193 } 194 195 196 //--------------------------------------------------------------------- 197 // Implementation of BeanFactory interface 198 //--------------------------------------------------------------------- 199 200 @Override 201 public Object getBean(String name) throws BeansException { 202 return doGetBean(name, null, null, false); 203 } 204 205 @Override 206 public <T> T getBean(String name, Class<T> requiredType) throws BeansException { 207 return doGetBean(name, requiredType, null, false); 208 } 209 210 @Override 211 public Object getBean(String name, Object... args) throws BeansException { 212 return doGetBean(name, null, args, false); 213 } 214 215 /** 216 * Return an instance, which may be shared or independent, of the specified bean. 217 * @param name the name of the bean to retrieve 218 * @param requiredType the required type of the bean to retrieve 219 * @param args arguments to use when creating a bean instance using explicit arguments 220 * (only applied when creating a new instance as opposed to retrieving an existing one) 221 * @return an instance of the bean 222 * @throws BeansException if the bean could not be created 223 */ 224 public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args) 225 throws BeansException { 226 227 return doGetBean(name, requiredType, args, false); 228 } 229 230 /** 231 * Return an instance, which may be shared or independent, of the specified bean. 232 * @param name the name of the bean to retrieve 233 * @param requiredType the required type of the bean to retrieve 234 * @param args arguments to use when creating a bean instance using explicit arguments 235 * (only applied when creating a new instance as opposed to retrieving an existing one) 236 * @param typeCheckOnly whether the instance is obtained for a type check, 237 * not for actual use 238 * @return an instance of the bean 239 * @throws BeansException if the bean could not be created 240 */ 241 @SuppressWarnings("unchecked") 242 protected <T> T doGetBean( 243 String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 244 throws BeansException { 245 246 String beanName = transformedBeanName(name); 247 Object bean; 248 249 // Eagerly check singleton cache for manually registered singletons. 250 Object sharedInstance = getSingleton(beanName); 251 if (sharedInstance != null && args == null) { 252 if (logger.isTraceEnabled()) { 253 if (isSingletonCurrentlyInCreation(beanName)) { 254 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + 255 "' that is not fully initialized yet - a consequence of a circular reference"); 256 } 257 else { 258 logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); 259 } 260 } 261 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 262 } 263 264 else { 265 // Fail if we're already creating this bean instance: 266 // We're assumably within a circular reference. 267 if (isPrototypeCurrentlyInCreation(beanName)) { 268 throw new BeanCurrentlyInCreationException(beanName); 269 } 270 271 // Check if bean definition exists in this factory. 272 BeanFactory parentBeanFactory = getParentBeanFactory(); 273 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 274 // Not found -> check parent. 275 String nameToLookup = originalBeanName(name); 276 if (parentBeanFactory instanceof AbstractBeanFactory) { 277 return ((AbstractBeanFactory) parentBeanFactory).doGetBean( 278 nameToLookup, requiredType, args, typeCheckOnly); 279 } 280 else if (args != null) { 281 // Delegation to parent with explicit args. 282 return (T) parentBeanFactory.getBean(nameToLookup, args); 283 } 284 else if (requiredType != null) { 285 // No args -> delegate to standard getBean method. 286 return parentBeanFactory.getBean(nameToLookup, requiredType); 287 } 288 else { 289 return (T) parentBeanFactory.getBean(nameToLookup); 290 } 291 } 292 293 if (!typeCheckOnly) { 294 markBeanAsCreated(beanName); 295 } 296 297 try { 298 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 299 checkMergedBeanDefinition(mbd, beanName, args); 300 301 // Guarantee initialization of beans that the current bean depends on. 302 String[] dependsOn = mbd.getDependsOn(); 303 if (dependsOn != null) { 304 for (String dep : dependsOn) { 305 if (isDependent(beanName, dep)) { 306 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 307 "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); 308 } 309 registerDependentBean(dep, beanName); 310 try { 311 getBean(dep); 312 } 313 catch (NoSuchBeanDefinitionException ex) { 314 throw new BeanCreationException(mbd.getResourceDescription(), beanName, 315 "'" + beanName + "' depends on missing bean '" + dep + "'", ex); 316 } 317 } 318 } 319 320 // Create bean instance. 321 if (mbd.isSingleton()) { 322 sharedInstance = getSingleton(beanName, () -> { 323 try { 324 return createBean(beanName, mbd, args); 325 } 326 catch (BeansException ex) { 327 // Explicitly remove instance from singleton cache: It might have been put there 328 // eagerly by the creation process, to allow for circular reference resolution. 329 // Also remove any beans that received a temporary reference to the bean. 330 destroySingleton(beanName); 331 throw ex; 332 } 333 }); 334 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 335 } 336 337 else if (mbd.isPrototype()) { 338 // It's a prototype -> create a new instance. 339 Object prototypeInstance = null; 340 try { 341 beforePrototypeCreation(beanName); 342 prototypeInstance = createBean(beanName, mbd, args); 343 } 344 finally { 345 afterPrototypeCreation(beanName); 346 } 347 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); 348 } 349 350 else { 351 String scopeName = mbd.getScope(); 352 if (!StringUtils.hasLength(scopeName)) { 353 throw new IllegalStateException("No scope name defined for bean 麓" + beanName + "'"); 354 } 355 Scope scope = this.scopes.get(scopeName); 356 if (scope == null) { 357 throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); 358 } 359 try { 360 Object scopedInstance = scope.get(beanName, () -> { 361 beforePrototypeCreation(beanName); 362 try { 363 return createBean(beanName, mbd, args); 364 } 365 finally { 366 afterPrototypeCreation(beanName); 367 } 368 }); 369 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); 370 } 371 catch (IllegalStateException ex) { 372 throw new BeanCreationException(beanName, 373 "Scope '" + scopeName + "' is not active for the current thread; consider " + 374 "defining a scoped proxy for this bean if you intend to refer to it from a singleton", 375 ex); 376 } 377 } 378 } 379 catch (BeansException ex) { 380 cleanupAfterBeanCreationFailure(beanName); 381 throw ex; 382 } 383 } 384 385 // Check if required type matches the type of the actual bean instance. 386 if (requiredType != null && !requiredType.isInstance(bean)) { 387 try { 388 T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); 389 if (convertedBean == null) { 390 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 391 } 392 return convertedBean; 393 } 394 catch (TypeMismatchException ex) { 395 if (logger.isTraceEnabled()) { 396 logger.trace("Failed to convert bean '" + name + "' to required type '" + 397 ClassUtils.getQualifiedName(requiredType) + "'", ex); 398 } 399 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); 400 } 401 } 402 return (T) bean; 403 } 404 405 @Override 406 public boolean containsBean(String name) { 407 String beanName = transformedBeanName(name); 408 if (containsSingleton(beanName) || containsBeanDefinition(beanName)) { 409 return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name)); 410 } 411 // Not found -> check parent. 412 BeanFactory parentBeanFactory = getParentBeanFactory(); 413 return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name))); 414 } 415 416 @Override 417 public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { 418 String beanName = transformedBeanName(name); 419 420 Object beanInstance = getSingleton(beanName, false); 421 if (beanInstance != null) { 422 if (beanInstance instanceof FactoryBean) { 423 return (BeanFactoryUtils.isFactoryDereference(name) || ((FactoryBean<?>) beanInstance).isSingleton()); 424 } 425 else { 426 return !BeanFactoryUtils.isFactoryDereference(name); 427 } 428 } 429 430 // No singleton instance found -> check bean definition. 431 BeanFactory parentBeanFactory = getParentBeanFactory(); 432 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 433 // No bean definition found in this factory -> delegate to parent. 434 return parentBeanFactory.isSingleton(originalBeanName(name)); 435 } 436 437 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 438 439 // In case of FactoryBean, return singleton status of created object if not a dereference. 440 if (mbd.isSingleton()) { 441 if (isFactoryBean(beanName, mbd)) { 442 if (BeanFactoryUtils.isFactoryDereference(name)) { 443 return true; 444 } 445 FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); 446 return factoryBean.isSingleton(); 447 } 448 else { 449 return !BeanFactoryUtils.isFactoryDereference(name); 450 } 451 } 452 else { 453 return false; 454 } 455 } 456 457 @Override 458 public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { 459 String beanName = transformedBeanName(name); 460 461 BeanFactory parentBeanFactory = getParentBeanFactory(); 462 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 463 // No bean definition found in this factory -> delegate to parent. 464 return parentBeanFactory.isPrototype(originalBeanName(name)); 465 } 466 467 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 468 if (mbd.isPrototype()) { 469 // In case of FactoryBean, return singleton status of created object if not a dereference. 470 return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName, mbd)); 471 } 472 473 // Singleton or scoped - not a prototype. 474 // However, FactoryBean may still produce a prototype object... 475 if (BeanFactoryUtils.isFactoryDereference(name)) { 476 return false; 477 } 478 if (isFactoryBean(beanName, mbd)) { 479 FactoryBean<?> fb = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); 480 if (System.getSecurityManager() != null) { 481 return AccessController.doPrivileged( 482 (PrivilegedAction<Boolean>) () -> 483 ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) || 484 !fb.isSingleton()), 485 getAccessControlContext()); 486 } 487 else { 488 return ((fb instanceof SmartFactoryBean && ((SmartFactoryBean<?>) fb).isPrototype()) || 489 !fb.isSingleton()); 490 } 491 } 492 else { 493 return false; 494 } 495 } 496 497 @Override 498 public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException { 499 return isTypeMatch(name, typeToMatch, true); 500 } 501 502 /** 503 * Internal extended variant of {@link #isTypeMatch(String, ResolvableType)} 504 * to check whether the bean with the given name matches the specified type. Allow 505 * additional constraints to be applied to ensure that beans are not created early. 506 * @param name the name of the bean to query 507 * @param typeToMatch the type to match against (as a 508 * {@code ResolvableType}) 509 * @return {@code true} if the bean type matches, {@code false} if it 510 * doesn't match or cannot be determined yet 511 * @throws NoSuchBeanDefinitionException if there is no bean with the given name 512 * @since 5.2 513 * @see #getBean 514 * @see #getType 515 */ 516 protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit) 517 throws NoSuchBeanDefinitionException { 518 519 String beanName = transformedBeanName(name); 520 boolean isFactoryDereference = BeanFactoryUtils.isFactoryDereference(name); 521 522 // Check manually registered singletons. 523 Object beanInstance = getSingleton(beanName, false); 524 if (beanInstance != null && beanInstance.getClass() != NullBean.class) { 525 if (beanInstance instanceof FactoryBean) { 526 if (!isFactoryDereference) { 527 Class<?> type = getTypeForFactoryBean((FactoryBean<?>) beanInstance); 528 return (type != null && typeToMatch.isAssignableFrom(type)); 529 } 530 else { 531 return typeToMatch.isInstance(beanInstance); 532 } 533 } 534 else if (!isFactoryDereference) { 535 if (typeToMatch.isInstance(beanInstance)) { 536 // Direct match for exposed instance? 537 return true; 538 } 539 else if (typeToMatch.hasGenerics() && containsBeanDefinition(beanName)) { 540 // Generics potentially only match on the target class, not on the proxy... 541 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 542 Class<?> targetType = mbd.getTargetType(); 543 if (targetType != null && targetType != ClassUtils.getUserClass(beanInstance)) { 544 // Check raw class match as well, making sure it's exposed on the proxy. 545 Class<?> classToMatch = typeToMatch.resolve(); 546 if (classToMatch != null && !classToMatch.isInstance(beanInstance)) { 547 return false; 548 } 549 if (typeToMatch.isAssignableFrom(targetType)) { 550 return true; 551 } 552 } 553 ResolvableType resolvableType = mbd.targetType; 554 if (resolvableType == null) { 555 resolvableType = mbd.factoryMethodReturnType; 556 } 557 return (resolvableType != null && typeToMatch.isAssignableFrom(resolvableType)); 558 } 559 } 560 return false; 561 } 562 else if (containsSingleton(beanName) && !containsBeanDefinition(beanName)) { 563 // null instance registered 564 return false; 565 } 566 567 // No singleton instance found -> check bean definition. 568 BeanFactory parentBeanFactory = getParentBeanFactory(); 569 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 570 // No bean definition found in this factory -> delegate to parent. 571 return parentBeanFactory.isTypeMatch(originalBeanName(name), typeToMatch); 572 } 573 574 // Retrieve corresponding bean definition. 575 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 576 BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); 577 578 // Setup the types that we want to match against 579 Class<?> classToMatch = typeToMatch.resolve(); 580 if (classToMatch == null) { 581 classToMatch = FactoryBean.class; 582 } 583 Class<?>[] typesToMatch = (FactoryBean.class == classToMatch ? 584 new Class<?>[] {classToMatch} : new Class<?>[] {FactoryBean.class, classToMatch}); 585 586 587 // Attempt to predict the bean type 588 Class<?> predictedType = null; 589 590 // We're looking for a regular reference but we're a factory bean that has 591 // a decorated bean definition. The target bean should be the same type 592 // as FactoryBean would ultimately return. 593 if (!isFactoryDereference && dbd != null && isFactoryBean(beanName, mbd)) { 594 // We should only attempt if the user explicitly set lazy-init to true 595 // and we know the merged bean definition is for a factory bean. 596 if (!mbd.isLazyInit() || allowFactoryBeanInit) { 597 RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd); 598 Class<?> targetType = predictBeanType(dbd.getBeanName(), tbd, typesToMatch); 599 if (targetType != null && !FactoryBean.class.isAssignableFrom(targetType)) { 600 predictedType = targetType; 601 } 602 } 603 } 604 605 // If we couldn't use the target type, try regular prediction. 606 if (predictedType == null) { 607 predictedType = predictBeanType(beanName, mbd, typesToMatch); 608 if (predictedType == null) { 609 return false; 610 } 611 } 612 613 // Attempt to get the actual ResolvableType for the bean. 614 ResolvableType beanType = null; 615 616 // If it's a FactoryBean, we want to look at what it creates, not the factory class. 617 if (FactoryBean.class.isAssignableFrom(predictedType)) { 618 if (beanInstance == null && !isFactoryDereference) { 619 beanType = getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit); 620 predictedType = beanType.resolve(); 621 if (predictedType == null) { 622 return false; 623 } 624 } 625 } 626 else if (isFactoryDereference) { 627 // Special case: A SmartInstantiationAwareBeanPostProcessor returned a non-FactoryBean 628 // type but we nevertheless are being asked to dereference a FactoryBean... 629 // Let's check the original bean class and proceed with it if it is a FactoryBean. 630 predictedType = predictBeanType(beanName, mbd, FactoryBean.class); 631 if (predictedType == null || !FactoryBean.class.isAssignableFrom(predictedType)) { 632 return false; 633 } 634 } 635 636 // We don't have an exact type but if bean definition target type or the factory 637 // method return type matches the predicted type then we can use that. 638 if (beanType == null) { 639 ResolvableType definedType = mbd.targetType; 640 if (definedType == null) { 641 definedType = mbd.factoryMethodReturnType; 642 } 643 if (definedType != null && definedType.resolve() == predictedType) { 644 beanType = definedType; 645 } 646 } 647 648 // If we have a bean type use it so that generics are considered 649 if (beanType != null) { 650 return typeToMatch.isAssignableFrom(beanType); 651 } 652 653 // If we don't have a bean type, fallback to the predicted type 654 return typeToMatch.isAssignableFrom(predictedType); 655 } 656 657 @Override 658 public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException { 659 return isTypeMatch(name, ResolvableType.forRawClass(typeToMatch)); 660 } 661 662 @Override 663 @Nullable 664 public Class<?> getType(String name) throws NoSuchBeanDefinitionException { 665 return getType(name, true); 666 } 667 668 @Override 669 @Nullable 670 public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException { 671 String beanName = transformedBeanName(name); 672 673 // Check manually registered singletons. 674 Object beanInstance = getSingleton(beanName, false); 675 if (beanInstance != null && beanInstance.getClass() != NullBean.class) { 676 if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) { 677 return getTypeForFactoryBean((FactoryBean<?>) beanInstance); 678 } 679 else { 680 return beanInstance.getClass(); 681 } 682 } 683 684 // No singleton instance found -> check bean definition. 685 BeanFactory parentBeanFactory = getParentBeanFactory(); 686 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 687 // No bean definition found in this factory -> delegate to parent. 688 return parentBeanFactory.getType(originalBeanName(name)); 689 } 690 691 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 692 693 // Check decorated bean definition, if any: We assume it'll be easier 694 // to determine the decorated bean's type than the proxy's type. 695 BeanDefinitionHolder dbd = mbd.getDecoratedDefinition(); 696 if (dbd != null && !BeanFactoryUtils.isFactoryDereference(name)) { 697 RootBeanDefinition tbd = getMergedBeanDefinition(dbd.getBeanName(), dbd.getBeanDefinition(), mbd); 698 Class<?> targetClass = predictBeanType(dbd.getBeanName(), tbd); 699 if (targetClass != null && !FactoryBean.class.isAssignableFrom(targetClass)) { 700 return targetClass; 701 } 702 } 703 704 Class<?> beanClass = predictBeanType(beanName, mbd); 705 706 // Check bean class whether we're dealing with a FactoryBean. 707 if (beanClass != null && FactoryBean.class.isAssignableFrom(beanClass)) { 708 if (!BeanFactoryUtils.isFactoryDereference(name)) { 709 // If it's a FactoryBean, we want to look at what it creates, not at the factory class. 710 return getTypeForFactoryBean(beanName, mbd, allowFactoryBeanInit).resolve(); 711 } 712 else { 713 return beanClass; 714 } 715 } 716 else { 717 return (!BeanFactoryUtils.isFactoryDereference(name) ? beanClass : null); 718 } 719 } 720 721 @Override 722 public String[] getAliases(String name) { 723 String beanName = transformedBeanName(name); 724 List<String> aliases = new ArrayList<>(); 725 boolean factoryPrefix = name.startsWith(FACTORY_BEAN_PREFIX); 726 String fullBeanName = beanName; 727 if (factoryPrefix) { 728 fullBeanName = FACTORY_BEAN_PREFIX + beanName; 729 } 730 if (!fullBeanName.equals(name)) { 731 aliases.add(fullBeanName); 732 } 733 String[] retrievedAliases = super.getAliases(beanName); 734 String prefix = factoryPrefix ? FACTORY_BEAN_PREFIX : ""; 735 for (String retrievedAlias : retrievedAliases) { 736 String alias = prefix + retrievedAlias; 737 if (!alias.equals(name)) { 738 aliases.add(alias); 739 } 740 } 741 if (!containsSingleton(beanName) && !containsBeanDefinition(beanName)) { 742 BeanFactory parentBeanFactory = getParentBeanFactory(); 743 if (parentBeanFactory != null) { 744 aliases.addAll(Arrays.asList(parentBeanFactory.getAliases(fullBeanName))); 745 } 746 } 747 return StringUtils.toStringArray(aliases); 748 } 749 750 751 //--------------------------------------------------------------------- 752 // Implementation of HierarchicalBeanFactory interface 753 //--------------------------------------------------------------------- 754 755 @Override 756 @Nullable 757 public BeanFactory getParentBeanFactory() { 758 return this.parentBeanFactory; 759 } 760 761 @Override 762 public boolean containsLocalBean(String name) { 763 String beanName = transformedBeanName(name); 764 return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) && 765 (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(beanName))); 766 } 767 768 769 //--------------------------------------------------------------------- 770 // Implementation of ConfigurableBeanFactory interface 771 //--------------------------------------------------------------------- 772 773 @Override 774 public void setParentBeanFactory(@Nullable BeanFactory parentBeanFactory) { 775 if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) { 776 throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory); 777 } 778 if (this == parentBeanFactory) { 779 throw new IllegalStateException("Cannot set parent bean factory to self"); 780 } 781 this.parentBeanFactory = parentBeanFactory; 782 } 783 784 @Override 785 public void setBeanClassLoader(@Nullable ClassLoader beanClassLoader) { 786 this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader()); 787 } 788 789 @Override 790 @Nullable 791 public ClassLoader getBeanClassLoader() { 792 return this.beanClassLoader; 793 } 794 795 @Override 796 public void setTempClassLoader(@Nullable ClassLoader tempClassLoader) { 797 this.tempClassLoader = tempClassLoader; 798 } 799 800 @Override 801 @Nullable 802 public ClassLoader getTempClassLoader() { 803 return this.tempClassLoader; 804 } 805 806 @Override 807 public void setCacheBeanMetadata(boolean cacheBeanMetadata) { 808 this.cacheBeanMetadata = cacheBeanMetadata; 809 } 810 811 @Override 812 public boolean isCacheBeanMetadata() { 813 return this.cacheBeanMetadata; 814 } 815 816 @Override 817 public void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver) { 818 this.beanExpressionResolver = resolver; 819 } 820 821 @Override 822 @Nullable 823 public BeanExpressionResolver getBeanExpressionResolver() { 824 return this.beanExpressionResolver; 825 } 826 827 @Override 828 public void setConversionService(@Nullable ConversionService conversionService) { 829 this.conversionService = conversionService; 830 } 831 832 @Override 833 @Nullable 834 public ConversionService getConversionService() { 835 return this.conversionService; 836 } 837 838 @Override 839 public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) { 840 Assert.notNull(registrar, "PropertyEditorRegistrar must not be null"); 841 this.propertyEditorRegistrars.add(registrar); 842 } 843 844 /** 845 * Return the set of PropertyEditorRegistrars. 846 */ 847 public Set<PropertyEditorRegistrar> getPropertyEditorRegistrars() { 848 return this.propertyEditorRegistrars; 849 } 850 851 @Override 852 public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) { 853 Assert.notNull(requiredType, "Required type must not be null"); 854 Assert.notNull(propertyEditorClass, "PropertyEditor class must not be null"); 855 this.customEditors.put(requiredType, propertyEditorClass); 856 } 857 858 @Override 859 public void copyRegisteredEditorsTo(PropertyEditorRegistry registry) { 860 registerCustomEditors(registry); 861 } 862 863 /** 864 * Return the map of custom editors, with Classes as keys and PropertyEditor classes as values. 865 */ 866 public Map<Class<?>, Class<? extends PropertyEditor>> getCustomEditors() { 867 return this.customEditors; 868 } 869 870 @Override 871 public void setTypeConverter(TypeConverter typeConverter) { 872 this.typeConverter = typeConverter; 873 } 874 875 /** 876 * Return the custom TypeConverter to use, if any. 877 * @return the custom TypeConverter, or {@code null} if none specified 878 */ 879 @Nullable 880 protected TypeConverter getCustomTypeConverter() { 881 return this.typeConverter; 882 } 883 884 @Override 885 public TypeConverter getTypeConverter() { 886 TypeConverter customConverter = getCustomTypeConverter(); 887 if (customConverter != null) { 888 return customConverter; 889 } 890 else { 891 // Build default TypeConverter, registering custom editors. 892 SimpleTypeConverter typeConverter = new SimpleTypeConverter(); 893 typeConverter.setConversionService(getConversionService()); 894 registerCustomEditors(typeConverter); 895 return typeConverter; 896 } 897 } 898 899 @Override 900 public void addEmbeddedValueResolver(StringValueResolver valueResolver) { 901 Assert.notNull(valueResolver, "StringValueResolver must not be null"); 902 this.embeddedValueResolvers.add(valueResolver); 903 } 904 905 @Override 906 public boolean hasEmbeddedValueResolver() { 907 return !this.embeddedValueResolvers.isEmpty(); 908 } 909 910 @Override 911 @Nullable 912 public String resolveEmbeddedValue(@Nullable String value) { 913 if (value == null) { 914 return null; 915 } 916 String result = value; 917 for (StringValueResolver resolver : this.embeddedValueResolvers) { 918 result = resolver.resolveStringValue(result); 919 if (result == null) { 920 return null; 921 } 922 } 923 return result; 924 } 925 926 @Override 927 public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { 928 Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); 929 // Remove from old position, if any 930 this.beanPostProcessors.remove(beanPostProcessor); 931 // Track whether it is instantiation/destruction aware 932 if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { 933 this.hasInstantiationAwareBeanPostProcessors = true; 934 } 935 if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { 936 this.hasDestructionAwareBeanPostProcessors = true; 937 } 938 // Add to end of list 939 this.beanPostProcessors.add(beanPostProcessor); 940 } 941 942 @Override 943 public int getBeanPostProcessorCount() { 944 return this.beanPostProcessors.size(); 945 } 946 947 /** 948 * Return the list of BeanPostProcessors that will get applied 949 * to beans created with this factory. 950 */ 951 public List<BeanPostProcessor> getBeanPostProcessors() { 952 return this.beanPostProcessors; 953 } 954 955 /** 956 * Return whether this factory holds a InstantiationAwareBeanPostProcessor 957 * that will get applied to singleton beans on creation. 958 * @see #addBeanPostProcessor 959 * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor 960 */ 961 protected boolean hasInstantiationAwareBeanPostProcessors() { 962 return this.hasInstantiationAwareBeanPostProcessors; 963 } 964 965 /** 966 * Return whether this factory holds a DestructionAwareBeanPostProcessor 967 * that will get applied to singleton beans on shutdown. 968 * @see #addBeanPostProcessor 969 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor 970 */ 971 protected boolean hasDestructionAwareBeanPostProcessors() { 972 return this.hasDestructionAwareBeanPostProcessors; 973 } 974 975 @Override 976 public void registerScope(String scopeName, Scope scope) { 977 Assert.notNull(scopeName, "Scope identifier must not be null"); 978 Assert.notNull(scope, "Scope must not be null"); 979 if (SCOPE_SINGLETON.equals(scopeName) || SCOPE_PROTOTYPE.equals(scopeName)) { 980 throw new IllegalArgumentException("Cannot replace existing scopes 'singleton' and 'prototype'"); 981 } 982 Scope previous = this.scopes.put(scopeName, scope); 983 if (previous != null && previous != scope) { 984 if (logger.isDebugEnabled()) { 985 logger.debug("Replacing scope '" + scopeName + "' from [" + previous + "] to [" + scope + "]"); 986 } 987 } 988 else { 989 if (logger.isTraceEnabled()) { 990 logger.trace("Registering scope '" + scopeName + "' with implementation [" + scope + "]"); 991 } 992 } 993 } 994 995 @Override 996 public String[] getRegisteredScopeNames() { 997 return StringUtils.toStringArray(this.scopes.keySet()); 998 } 999 1000 @Override 1001 @Nullable 1002 public Scope getRegisteredScope(String scopeName) { 1003 Assert.notNull(scopeName, "Scope identifier must not be null"); 1004 return this.scopes.get(scopeName); 1005 } 1006 1007 /** 1008 * Set the security context provider for this bean factory. If a security manager 1009 * is set, interaction with the user code will be executed using the privileged 1010 * of the provided security context. 1011 */ 1012 public void setSecurityContextProvider(SecurityContextProvider securityProvider) { 1013 this.securityContextProvider = securityProvider; 1014 } 1015 1016 /** 1017 * Delegate the creation of the access control context to the 1018 * {@link #setSecurityContextProvider SecurityContextProvider}. 1019 */ 1020 @Override 1021 public AccessControlContext getAccessControlContext() { 1022 return (this.securityContextProvider != null ? 1023 this.securityContextProvider.getAccessControlContext() : 1024 AccessController.getContext()); 1025 } 1026 1027 @Override 1028 public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) { 1029 Assert.notNull(otherFactory, "BeanFactory must not be null"); 1030 setBeanClassLoader(otherFactory.getBeanClassLoader()); 1031 setCacheBeanMetadata(otherFactory.isCacheBeanMetadata()); 1032 setBeanExpressionResolver(otherFactory.getBeanExpressionResolver()); 1033 setConversionService(otherFactory.getConversionService()); 1034 if (otherFactory instanceof AbstractBeanFactory) { 1035 AbstractBeanFactory otherAbstractFactory = (AbstractBeanFactory) otherFactory; 1036 this.propertyEditorRegistrars.addAll(otherAbstractFactory.propertyEditorRegistrars); 1037 this.customEditors.putAll(otherAbstractFactory.customEditors); 1038 this.typeConverter = otherAbstractFactory.typeConverter; 1039 this.beanPostProcessors.addAll(otherAbstractFactory.beanPostProcessors); 1040 this.hasInstantiationAwareBeanPostProcessors = this.hasInstantiationAwareBeanPostProcessors || 1041 otherAbstractFactory.hasInstantiationAwareBeanPostProcessors; 1042 this.hasDestructionAwareBeanPostProcessors = this.hasDestructionAwareBeanPostProcessors || 1043 otherAbstractFactory.hasDestructionAwareBeanPostProcessors; 1044 this.scopes.putAll(otherAbstractFactory.scopes); 1045 this.securityContextProvider = otherAbstractFactory.securityContextProvider; 1046 } 1047 else { 1048 setTypeConverter(otherFactory.getTypeConverter()); 1049 String[] otherScopeNames = otherFactory.getRegisteredScopeNames(); 1050 for (String scopeName : otherScopeNames) { 1051 this.scopes.put(scopeName, otherFactory.getRegisteredScope(scopeName)); 1052 } 1053 } 1054 } 1055 1056 /** 1057 * Return a 'merged' BeanDefinition for the given bean name, 1058 * merging a child bean definition with its parent if necessary. 1059 * <p>This {@code getMergedBeanDefinition} considers bean definition 1060 * in ancestors as well. 1061 * @param name the name of the bean to retrieve the merged definition for 1062 * (may be an alias) 1063 * @return a (potentially merged) RootBeanDefinition for the given bean 1064 * @throws NoSuchBeanDefinitionException if there is no bean with the given name 1065 * @throws BeanDefinitionStoreException in case of an invalid bean definition 1066 */ 1067 @Override 1068 public BeanDefinition getMergedBeanDefinition(String name) throws BeansException { 1069 String beanName = transformedBeanName(name); 1070 // Efficiently check whether bean definition exists in this factory. 1071 if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) { 1072 return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName); 1073 } 1074 // Resolve merged bean definition locally. 1075 return getMergedLocalBeanDefinition(beanName); 1076 } 1077 1078 @Override 1079 public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException { 1080 String beanName = transformedBeanName(name); 1081 Object beanInstance = getSingleton(beanName, false); 1082 if (beanInstance != null) { 1083 return (beanInstance instanceof FactoryBean); 1084 } 1085 // No singleton instance found -> check bean definition. 1086 if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) { 1087 // No bean definition found in this factory -> delegate to parent. 1088 return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name); 1089 } 1090 return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName)); 1091 } 1092 1093 @Override 1094 public boolean isActuallyInCreation(String beanName) { 1095 return (isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName)); 1096 } 1097 1098 /** 1099 * Return whether the specified prototype bean is currently in creation 1100 * (within the current thread). 1101 * @param beanName the name of the bean 1102 */ 1103 protected boolean isPrototypeCurrentlyInCreation(String beanName) { 1104 Object curVal = this.prototypesCurrentlyInCreation.get(); 1105 return (curVal != null && 1106 (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); 1107 } 1108 1109 /** 1110 * Callback before prototype creation. 1111 * <p>The default implementation register the prototype as currently in creation. 1112 * @param beanName the name of the prototype about to be created 1113 * @see #isPrototypeCurrentlyInCreation 1114 */ 1115 @SuppressWarnings("unchecked") 1116 protected void beforePrototypeCreation(String beanName) { 1117 Object curVal = this.prototypesCurrentlyInCreation.get(); 1118 if (curVal == null) { 1119 this.prototypesCurrentlyInCreation.set(beanName); 1120 } 1121 else if (curVal instanceof String) { 1122 Set<String> beanNameSet = new HashSet<>(2); 1123 beanNameSet.add((String) curVal); 1124 beanNameSet.add(beanName); 1125 this.prototypesCurrentlyInCreation.set(beanNameSet); 1126 } 1127 else { 1128 Set<String> beanNameSet = (Set<String>) curVal; 1129 beanNameSet.add(beanName); 1130 } 1131 } 1132 1133 /** 1134 * Callback after prototype creation. 1135 * <p>The default implementation marks the prototype as not in creation anymore. 1136 * @param beanName the name of the prototype that has been created 1137 * @see #isPrototypeCurrentlyInCreation 1138 */ 1139 @SuppressWarnings("unchecked") 1140 protected void afterPrototypeCreation(String beanName) { 1141 Object curVal = this.prototypesCurrentlyInCreation.get(); 1142 if (curVal instanceof String) { 1143 this.prototypesCurrentlyInCreation.remove(); 1144 } 1145 else if (curVal instanceof Set) { 1146 Set<String> beanNameSet = (Set<String>) curVal; 1147 beanNameSet.remove(beanName); 1148 if (beanNameSet.isEmpty()) { 1149 this.prototypesCurrentlyInCreation.remove(); 1150 } 1151 } 1152 } 1153 1154 @Override 1155 public void destroyBean(String beanName, Object beanInstance) { 1156 destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName)); 1157 } 1158 1159 /** 1160 * Destroy the given bean instance (usually a prototype instance 1161 * obtained from this factory) according to the given bean definition. 1162 * @param beanName the name of the bean definition 1163 * @param bean the bean instance to destroy 1164 * @param mbd the merged bean definition 1165 */ 1166 protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) { 1167 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy(); 1168 } 1169 1170 @Override 1171 public void destroyScopedBean(String beanName) { 1172 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 1173 if (mbd.isSingleton() || mbd.isPrototype()) { 1174 throw new IllegalArgumentException( 1175 "Bean name '" + beanName + "' does not correspond to an object in a mutable scope"); 1176 } 1177 String scopeName = mbd.getScope(); 1178 Scope scope = this.scopes.get(scopeName); 1179 if (scope == null) { 1180 throw new IllegalStateException("No Scope SPI registered for scope name '" + scopeName + "'"); 1181 } 1182 Object bean = scope.remove(beanName); 1183 if (bean != null) { 1184 destroyBean(beanName, bean, mbd); 1185 } 1186 } 1187 1188 1189 //--------------------------------------------------------------------- 1190 // Implementation methods 1191 //--------------------------------------------------------------------- 1192 1193 /** 1194 * Return the bean name, stripping out the factory dereference prefix if necessary, 1195 * and resolving aliases to canonical names. 1196 * @param name the user-specified name 1197 * @return the transformed bean name 1198 */ 1199 protected String transformedBeanName(String name) { 1200 return canonicalName(BeanFactoryUtils.transformedBeanName(name)); 1201 } 1202 1203 /** 1204 * Determine the original bean name, resolving locally defined aliases to canonical names. 1205 * @param name the user-specified name 1206 * @return the original bean name 1207 */ 1208 protected String originalBeanName(String name) { 1209 String beanName = transformedBeanName(name); 1210 if (name.startsWith(FACTORY_BEAN_PREFIX)) { 1211 beanName = FACTORY_BEAN_PREFIX + beanName; 1212 } 1213 return beanName; 1214 } 1215 1216 /** 1217 * Initialize the given BeanWrapper with the custom editors registered 1218 * with this factory. To be called for BeanWrappers that will create 1219 * and populate bean instances. 1220 * <p>The default implementation delegates to {@link #registerCustomEditors}. 1221 * Can be overridden in subclasses. 1222 * @param bw the BeanWrapper to initialize 1223 */ 1224 protected void initBeanWrapper(BeanWrapper bw) { 1225 bw.setConversionService(getConversionService()); 1226 registerCustomEditors(bw); 1227 } 1228 1229 /** 1230 * Initialize the given PropertyEditorRegistry with the custom editors 1231 * that have been registered with this BeanFactory. 1232 * <p>To be called for BeanWrappers that will create and populate bean 1233 * instances, and for SimpleTypeConverter used for constructor argument 1234 * and factory method type conversion. 1235 * @param registry the PropertyEditorRegistry to initialize 1236 */ 1237 protected void registerCustomEditors(PropertyEditorRegistry registry) { 1238 PropertyEditorRegistrySupport registrySupport = 1239 (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null); 1240 if (registrySupport != null) { 1241 registrySupport.useConfigValueEditors(); 1242 } 1243 if (!this.propertyEditorRegistrars.isEmpty()) { 1244 for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) { 1245 try { 1246 registrar.registerCustomEditors(registry); 1247 } 1248 catch (BeanCreationException ex) { 1249 Throwable rootCause = ex.getMostSpecificCause(); 1250 if (rootCause instanceof BeanCurrentlyInCreationException) { 1251 BeanCreationException bce = (BeanCreationException) rootCause; 1252 String bceBeanName = bce.getBeanName(); 1253 if (bceBeanName != null && isCurrentlyInCreation(bceBeanName)) { 1254 if (logger.isDebugEnabled()) { 1255 logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() + 1256 "] failed because it tried to obtain currently created bean '" + 1257 ex.getBeanName() + "': " + ex.getMessage()); 1258 } 1259 onSuppressedException(ex); 1260 continue; 1261 } 1262 } 1263 throw ex; 1264 } 1265 } 1266 } 1267 if (!this.customEditors.isEmpty()) { 1268 this.customEditors.forEach((requiredType, editorClass) -> 1269 registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass))); 1270 } 1271 } 1272 1273 1274 /** 1275 * Return a merged RootBeanDefinition, traversing the parent bean definition 1276 * if the specified bean corresponds to a child bean definition. 1277 * @param beanName the name of the bean to retrieve the merged definition for 1278 * @return a (potentially merged) RootBeanDefinition for the given bean 1279 * @throws NoSuchBeanDefinitionException if there is no bean with the given name 1280 * @throws BeanDefinitionStoreException in case of an invalid bean definition 1281 */ 1282 protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException { 1283 // Quick check on the concurrent map first, with minimal locking. 1284 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName); 1285 if (mbd != null && !mbd.stale) { 1286 return mbd; 1287 } 1288 return getMergedBeanDefinition(beanName, getBeanDefinition(beanName)); 1289 } 1290 1291 /** 1292 * Return a RootBeanDefinition for the given top-level bean, by merging with 1293 * the parent if the given bean's definition is a child bean definition. 1294 * @param beanName the name of the bean definition 1295 * @param bd the original bean definition (Root/ChildBeanDefinition) 1296 * @return a (potentially merged) RootBeanDefinition for the given bean 1297 * @throws BeanDefinitionStoreException in case of an invalid bean definition 1298 */ 1299 protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd) 1300 throws BeanDefinitionStoreException { 1301 1302 return getMergedBeanDefinition(beanName, bd, null); 1303 } 1304 1305 /** 1306 * Return a RootBeanDefinition for the given bean, by merging with the 1307 * parent if the given bean's definition is a child bean definition. 1308 * @param beanName the name of the bean definition 1309 * @param bd the original bean definition (Root/ChildBeanDefinition) 1310 * @param containingBd the containing bean definition in case of inner bean, 1311 * or {@code null} in case of a top-level bean 1312 * @return a (potentially merged) RootBeanDefinition for the given bean 1313 * @throws BeanDefinitionStoreException in case of an invalid bean definition 1314 */ 1315 protected RootBeanDefinition getMergedBeanDefinition( 1316 String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd) 1317 throws BeanDefinitionStoreException { 1318 1319 synchronized (this.mergedBeanDefinitions) { 1320 RootBeanDefinition mbd = null; 1321 RootBeanDefinition previous = null; 1322 1323 // Check with full lock now in order to enforce the same merged instance. 1324 if (containingBd == null) { 1325 mbd = this.mergedBeanDefinitions.get(beanName); 1326 } 1327 1328 if (mbd == null || mbd.stale) { 1329 previous = mbd; 1330 if (bd.getParentName() == null) { 1331 // Use copy of given root bean definition. 1332 if (bd instanceof RootBeanDefinition) { 1333 mbd = ((RootBeanDefinition) bd).cloneBeanDefinition(); 1334 } 1335 else { 1336 mbd = new RootBeanDefinition(bd); 1337 } 1338 } 1339 else { 1340 // Child bean definition: needs to be merged with parent. 1341 BeanDefinition pbd; 1342 try { 1343 String parentBeanName = transformedBeanName(bd.getParentName()); 1344 if (!beanName.equals(parentBeanName)) { 1345 pbd = getMergedBeanDefinition(parentBeanName); 1346 } 1347 else { 1348 BeanFactory parent = getParentBeanFactory(); 1349 if (parent instanceof ConfigurableBeanFactory) { 1350 pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName); 1351 } 1352 else { 1353 throw new NoSuchBeanDefinitionException(parentBeanName, 1354 "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName + 1355 "': cannot be resolved without a ConfigurableBeanFactory parent"); 1356 } 1357 } 1358 } 1359 catch (NoSuchBeanDefinitionException ex) { 1360 throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName, 1361 "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex); 1362 } 1363 // Deep copy with overridden values. 1364 mbd = new RootBeanDefinition(pbd); 1365 mbd.overrideFrom(bd); 1366 } 1367 1368 // Set default singleton scope, if not configured before. 1369 if (!StringUtils.hasLength(mbd.getScope())) { 1370 mbd.setScope(SCOPE_SINGLETON); 1371 } 1372 1373 // A bean contained in a non-singleton bean cannot be a singleton itself. 1374 // Let's correct this on the fly here, since this might be the result of 1375 // parent-child merging for the outer bean, in which case the original inner bean 1376 // definition will not have inherited the merged outer bean's singleton status. 1377 if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) { 1378 mbd.setScope(containingBd.getScope()); 1379 } 1380 1381 // Cache the merged bean definition for the time being 1382 // (it might still get re-merged later on in order to pick up metadata changes) 1383 if (containingBd == null && isCacheBeanMetadata()) { 1384 this.mergedBeanDefinitions.put(beanName, mbd); 1385 } 1386 } 1387 if (previous != null) { 1388 copyRelevantMergedBeanDefinitionCaches(previous, mbd); 1389 } 1390 return mbd; 1391 } 1392 } 1393 1394 private void copyRelevantMergedBeanDefinitionCaches(RootBeanDefinition previous, RootBeanDefinition mbd) { 1395 if (ObjectUtils.nullSafeEquals(mbd.getBeanClassName(), previous.getBeanClassName()) && 1396 ObjectUtils.nullSafeEquals(mbd.getFactoryBeanName(), previous.getFactoryBeanName()) && 1397 ObjectUtils.nullSafeEquals(mbd.getFactoryMethodName(), previous.getFactoryMethodName())) { 1398 ResolvableType targetType = mbd.targetType; 1399 ResolvableType previousTargetType = previous.targetType; 1400 if (targetType == null || targetType.equals(previousTargetType)) { 1401 mbd.targetType = previousTargetType; 1402 mbd.isFactoryBean = previous.isFactoryBean; 1403 mbd.resolvedTargetType = previous.resolvedTargetType; 1404 mbd.factoryMethodReturnType = previous.factoryMethodReturnType; 1405 mbd.factoryMethodToIntrospect = previous.factoryMethodToIntrospect; 1406 } 1407 } 1408 } 1409 1410 /** 1411 * Check the given merged bean definition, 1412 * potentially throwing validation exceptions. 1413 * @param mbd the merged bean definition to check 1414 * @param beanName the name of the bean 1415 * @param args the arguments for bean creation, if any 1416 * @throws BeanDefinitionStoreException in case of validation failure 1417 */ 1418 protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args) 1419 throws BeanDefinitionStoreException { 1420 1421 if (mbd.isAbstract()) { 1422 throw new BeanIsAbstractException(beanName); 1423 } 1424 } 1425 1426 /** 1427 * Remove the merged bean definition for the specified bean, 1428 * recreating it on next access. 1429 * @param beanName the bean name to clear the merged definition for 1430 */ 1431 protected void clearMergedBeanDefinition(String beanName) { 1432 RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName); 1433 if (bd != null) { 1434 bd.stale = true; 1435 } 1436 } 1437 1438 /** 1439 * Clear the merged bean definition cache, removing entries for beans 1440 * which are not considered eligible for full metadata caching yet. 1441 * <p>Typically triggered after changes to the original bean definitions, 1442 * e.g. after applying a {@code BeanFactoryPostProcessor}. Note that metadata 1443 * for beans which have already been created at this point will be kept around. 1444 * @since 4.2 1445 */ 1446 public void clearMetadataCache() { 1447 this.mergedBeanDefinitions.forEach((beanName, bd) -> { 1448 if (!isBeanEligibleForMetadataCaching(beanName)) { 1449 bd.stale = true; 1450 } 1451 }); 1452 } 1453 1454 /** 1455 * Resolve the bean class for the specified bean definition, 1456 * resolving a bean class name into a Class reference (if necessary) 1457 * and storing the resolved Class in the bean definition for further use. 1458 * @param mbd the merged bean definition to determine the class for 1459 * @param beanName the name of the bean (for error handling purposes) 1460 * @param typesToMatch the types to match in case of internal type matching purposes 1461 * (also signals that the returned {@code Class} will never be exposed to application code) 1462 * @return the resolved bean class (or {@code null} if none) 1463 * @throws CannotLoadBeanClassException if we failed to load the class 1464 */ 1465 @Nullable 1466 protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch) 1467 throws CannotLoadBeanClassException { 1468 1469 try { 1470 if (mbd.hasBeanClass()) { 1471 return mbd.getBeanClass(); 1472 } 1473 if (System.getSecurityManager() != null) { 1474 return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) 1475 () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); 1476 } 1477 else { 1478 return doResolveBeanClass(mbd, typesToMatch); 1479 } 1480 } 1481 catch (PrivilegedActionException pae) { 1482 ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); 1483 throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); 1484 } 1485 catch (ClassNotFoundException ex) { 1486 throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); 1487 } 1488 catch (LinkageError err) { 1489 throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); 1490 } 1491 } 1492 1493 @Nullable 1494 private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch) 1495 throws ClassNotFoundException { 1496 1497 ClassLoader beanClassLoader = getBeanClassLoader(); 1498 ClassLoader dynamicLoader = beanClassLoader; 1499 boolean freshResolve = false; 1500 1501 if (!ObjectUtils.isEmpty(typesToMatch)) { 1502 // When just doing type checks (i.e. not creating an actual instance yet), 1503 // use the specified temporary class loader (e.g. in a weaving scenario). 1504 ClassLoader tempClassLoader = getTempClassLoader(); 1505 if (tempClassLoader != null) { 1506 dynamicLoader = tempClassLoader; 1507 freshResolve = true; 1508 if (tempClassLoader instanceof DecoratingClassLoader) { 1509 DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader; 1510 for (Class<?> typeToMatch : typesToMatch) { 1511 dcl.excludeClass(typeToMatch.getName()); 1512 } 1513 } 1514 } 1515 } 1516 1517 String className = mbd.getBeanClassName(); 1518 if (className != null) { 1519 Object evaluated = evaluateBeanDefinitionString(className, mbd); 1520 if (!className.equals(evaluated)) { 1521 // A dynamically resolved expression, supported as of 4.2... 1522 if (evaluated instanceof Class) { 1523 return (Class<?>) evaluated; 1524 } 1525 else if (evaluated instanceof String) { 1526 className = (String) evaluated; 1527 freshResolve = true; 1528 } 1529 else { 1530 throw new IllegalStateException("Invalid class name expression result: " + evaluated); 1531 } 1532 } 1533 if (freshResolve) { 1534 // When resolving against a temporary class loader, exit early in order 1535 // to avoid storing the resolved Class in the bean definition. 1536 if (dynamicLoader != null) { 1537 try { 1538 return dynamicLoader.loadClass(className); 1539 } 1540 catch (ClassNotFoundException ex) { 1541 if (logger.isTraceEnabled()) { 1542 logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex); 1543 } 1544 } 1545 } 1546 return ClassUtils.forName(className, dynamicLoader); 1547 } 1548 } 1549 1550 // Resolve regularly, caching the result in the BeanDefinition... 1551 return mbd.resolveBeanClass(beanClassLoader); 1552 } 1553 1554 /** 1555 * Evaluate the given String as contained in a bean definition, 1556 * potentially resolving it as an expression. 1557 * @param value the value to check 1558 * @param beanDefinition the bean definition that the value comes from 1559 * @return the resolved value 1560 * @see #setBeanExpressionResolver 1561 */ 1562 @Nullable 1563 protected Object evaluateBeanDefinitionString(@Nullable String value, @Nullable BeanDefinition beanDefinition) { 1564 if (this.beanExpressionResolver == null) { 1565 return value; 1566 } 1567 1568 Scope scope = null; 1569 if (beanDefinition != null) { 1570 String scopeName = beanDefinition.getScope(); 1571 if (scopeName != null) { 1572 scope = getRegisteredScope(scopeName); 1573 } 1574 } 1575 return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope)); 1576 } 1577 1578 1579 /** 1580 * Predict the eventual bean type (of the processed bean instance) for the 1581 * specified bean. Called by {@link #getType} and {@link #isTypeMatch}. 1582 * Does not need to handle FactoryBeans specifically, since it is only 1583 * supposed to operate on the raw bean type. 1584 * <p>This implementation is simplistic in that it is not able to 1585 * handle factory methods and InstantiationAwareBeanPostProcessors. 1586 * It only predicts the bean type correctly for a standard bean. 1587 * To be overridden in subclasses, applying more sophisticated type detection. 1588 * @param beanName the name of the bean 1589 * @param mbd the merged bean definition to determine the type for 1590 * @param typesToMatch the types to match in case of internal type matching purposes 1591 * (also signals that the returned {@code Class} will never be exposed to application code) 1592 * @return the type of the bean, or {@code null} if not predictable 1593 */ 1594 @Nullable 1595 protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) { 1596 Class<?> targetType = mbd.getTargetType(); 1597 if (targetType != null) { 1598 return targetType; 1599 } 1600 if (mbd.getFactoryMethodName() != null) { 1601 return null; 1602 } 1603 return resolveBeanClass(mbd, beanName, typesToMatch); 1604 } 1605 1606 /** 1607 * Check whether the given bean is defined as a {@link FactoryBean}. 1608 * @param beanName the name of the bean 1609 * @param mbd the corresponding bean definition 1610 */ 1611 protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) { 1612 Boolean result = mbd.isFactoryBean; 1613 if (result == null) { 1614 Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class); 1615 result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType)); 1616 mbd.isFactoryBean = result; 1617 } 1618 return result; 1619 } 1620 1621 /** 1622 * Determine the bean type for the given FactoryBean definition, as far as possible. 1623 * Only called if there is no singleton instance registered for the target bean 1624 * already. The implementation is allowed to instantiate the target factory bean if 1625 * {@code allowInit} is {@code true} and the type cannot be determined another way; 1626 * otherwise it is restricted to introspecting signatures and related metadata. 1627 * <p>If no {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} if set on the bean definition 1628 * and {@code allowInit} is {@code true}, the default implementation will create 1629 * the FactoryBean via {@code getBean} to call its {@code getObjectType} method. 1630 * Subclasses are encouraged to optimize this, typically by inspecting the generic 1631 * signature of the factory bean class or the factory method that creates it. 1632 * If subclasses do instantiate the FactoryBean, they should consider trying the 1633 * {@code getObjectType} method without fully populating the bean. If this fails, 1634 * a full FactoryBean creation as performed by this implementation should be used 1635 * as fallback. 1636 * @param beanName the name of the bean 1637 * @param mbd the merged bean definition for the bean 1638 * @param allowInit if initialization of the FactoryBean is permitted if the type 1639 * cannot be determined another way 1640 * @return the type for the bean if determinable, otherwise {@code ResolvableType.NONE} 1641 * @since 5.2 1642 * @see org.springframework.beans.factory.FactoryBean#getObjectType() 1643 * @see #getBean(String) 1644 */ 1645 protected ResolvableType getTypeForFactoryBean(String beanName, RootBeanDefinition mbd, boolean allowInit) { 1646 ResolvableType result = getTypeForFactoryBeanFromAttributes(mbd); 1647 if (result != ResolvableType.NONE) { 1648 return result; 1649 } 1650 1651 if (allowInit && mbd.isSingleton()) { 1652 try { 1653 FactoryBean<?> factoryBean = doGetBean(FACTORY_BEAN_PREFIX + beanName, FactoryBean.class, null, true); 1654 Class<?> objectType = getTypeForFactoryBean(factoryBean); 1655 return (objectType != null ? ResolvableType.forClass(objectType) : ResolvableType.NONE); 1656 } 1657 catch (BeanCreationException ex) { 1658 if (ex.contains(BeanCurrentlyInCreationException.class)) { 1659 logger.trace(LogMessage.format("Bean currently in creation on FactoryBean type check: %s", ex)); 1660 } 1661 else if (mbd.isLazyInit()) { 1662 logger.trace(LogMessage.format("Bean creation exception on lazy FactoryBean type check: %s", ex)); 1663 } 1664 else { 1665 logger.debug(LogMessage.format("Bean creation exception on eager FactoryBean type check: %s", ex)); 1666 } 1667 onSuppressedException(ex); 1668 } 1669 } 1670 return ResolvableType.NONE; 1671 } 1672 1673 /** 1674 * Determine the bean type for a FactoryBean by inspecting its attributes for a 1675 * {@link FactoryBean#OBJECT_TYPE_ATTRIBUTE} value. 1676 * @param attributes the attributes to inspect 1677 * @return a {@link ResolvableType} extracted from the attributes or 1678 * {@code ResolvableType.NONE} 1679 * @since 5.2 1680 */ 1681 ResolvableType getTypeForFactoryBeanFromAttributes(AttributeAccessor attributes) { 1682 Object attribute = attributes.getAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE); 1683 if (attribute instanceof ResolvableType) { 1684 return (ResolvableType) attribute; 1685 } 1686 if (attribute instanceof Class) { 1687 return ResolvableType.forClass((Class<?>) attribute); 1688 } 1689 return ResolvableType.NONE; 1690 } 1691 1692 /** 1693 * Determine the bean type for the given FactoryBean definition, as far as possible. 1694 * Only called if there is no singleton instance registered for the target bean already. 1695 * <p>The default implementation creates the FactoryBean via {@code getBean} 1696 * to call its {@code getObjectType} method. Subclasses are encouraged to optimize 1697 * this, typically by just instantiating the FactoryBean but not populating it yet, 1698 * trying whether its {@code getObjectType} method already returns a type. 1699 * If no type found, a full FactoryBean creation as performed by this implementation 1700 * should be used as fallback. 1701 * @param beanName the name of the bean 1702 * @param mbd the merged bean definition for the bean 1703 * @return the type for the bean if determinable, or {@code null} otherwise 1704 * @see org.springframework.beans.factory.FactoryBean#getObjectType() 1705 * @see #getBean(String) 1706 * @deprecated since 5.2 in favor of {@link #getTypeForFactoryBean(String, RootBeanDefinition, boolean)} 1707 */ 1708 @Nullable 1709 @Deprecated 1710 protected Class<?> getTypeForFactoryBean(String beanName, RootBeanDefinition mbd) { 1711 return getTypeForFactoryBean(beanName, mbd, true).resolve(); 1712 } 1713 1714 /** 1715 * Mark the specified bean as already created (or about to be created). 1716 * <p>This allows the bean factory to optimize its caching for repeated 1717 * creation of the specified bean. 1718 * @param beanName the name of the bean 1719 */ 1720 protected void markBeanAsCreated(String beanName) { 1721 if (!this.alreadyCreated.contains(beanName)) { 1722 synchronized (this.mergedBeanDefinitions) { 1723 if (!this.alreadyCreated.contains(beanName)) { 1724 // Let the bean definition get re-merged now that we're actually creating 1725 // the bean... just in case some of its metadata changed in the meantime. 1726 clearMergedBeanDefinition(beanName); 1727 this.alreadyCreated.add(beanName); 1728 } 1729 } 1730 } 1731 } 1732 1733 /** 1734 * Perform appropriate cleanup of cached metadata after bean creation failed. 1735 * @param beanName the name of the bean 1736 */ 1737 protected void cleanupAfterBeanCreationFailure(String beanName) { 1738 synchronized (this.mergedBeanDefinitions) { 1739 this.alreadyCreated.remove(beanName); 1740 } 1741 } 1742 1743 /** 1744 * Determine whether the specified bean is eligible for having 1745 * its bean definition metadata cached. 1746 * @param beanName the name of the bean 1747 * @return {@code true} if the bean's metadata may be cached 1748 * at this point already 1749 */ 1750 protected boolean isBeanEligibleForMetadataCaching(String beanName) { 1751 return this.alreadyCreated.contains(beanName); 1752 } 1753 1754 /** 1755 * Remove the singleton instance (if any) for the given bean name, 1756 * but only if it hasn't been used for other purposes than type checking. 1757 * @param beanName the name of the bean 1758 * @return {@code true} if actually removed, {@code false} otherwise 1759 */ 1760 protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) { 1761 if (!this.alreadyCreated.contains(beanName)) { 1762 removeSingleton(beanName); 1763 return true; 1764 } 1765 else { 1766 return false; 1767 } 1768 } 1769 1770 /** 1771 * Check whether this factory's bean creation phase already started, 1772 * i.e. whether any bean has been marked as created in the meantime. 1773 * @since 4.2.2 1774 * @see #markBeanAsCreated 1775 */ 1776 protected boolean hasBeanCreationStarted() { 1777 return !this.alreadyCreated.isEmpty(); 1778 } 1779 1780 /** 1781 * Get the object for the given bean instance, either the bean 1782 * instance itself or its created object in case of a FactoryBean. 1783 * @param beanInstance the shared bean instance 1784 * @param name the name that may include factory dereference prefix 1785 * @param beanName the canonical bean name 1786 * @param mbd the merged bean definition 1787 * @return the object to expose for the bean 1788 */ 1789 protected Object getObjectForBeanInstance( 1790 Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) { 1791 1792 // Don't let calling code try to dereference the factory if the bean isn't a factory. 1793 if (BeanFactoryUtils.isFactoryDereference(name)) { 1794 if (beanInstance instanceof NullBean) { 1795 return beanInstance; 1796 } 1797 if (!(beanInstance instanceof FactoryBean)) { 1798 throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass()); 1799 } 1800 if (mbd != null) { 1801 mbd.isFactoryBean = true; 1802 } 1803 return beanInstance; 1804 } 1805 1806 // Now we have the bean instance, which may be a normal bean or a FactoryBean. 1807 // If it's a FactoryBean, we use it to create a bean instance, unless the 1808 // caller actually wants a reference to the factory. 1809 if (!(beanInstance instanceof FactoryBean)) { 1810 return beanInstance; 1811 } 1812 1813 Object object = null; 1814 if (mbd != null) { 1815 mbd.isFactoryBean = true; 1816 } 1817 else { 1818 object = getCachedObjectForFactoryBean(beanName); 1819 } 1820 if (object == null) { 1821 // Return bean instance from factory. 1822 FactoryBean<?> factory = (FactoryBean<?>) beanInstance; 1823 // Caches object obtained from FactoryBean if it is a singleton. 1824 if (mbd == null && containsBeanDefinition(beanName)) { 1825 mbd = getMergedLocalBeanDefinition(beanName); 1826 } 1827 boolean synthetic = (mbd != null && mbd.isSynthetic()); 1828 object = getObjectFromFactoryBean(factory, beanName, !synthetic); 1829 } 1830 return object; 1831 } 1832 1833 /** 1834 * Determine whether the given bean name is already in use within this factory, 1835 * i.e. whether there is a local bean or alias registered under this name or 1836 * an inner bean created with this name. 1837 * @param beanName the name to check 1838 */ 1839 public boolean isBeanNameInUse(String beanName) { 1840 return isAlias(beanName) || containsLocalBean(beanName) || hasDependentBean(beanName); 1841 } 1842 1843 /** 1844 * Determine whether the given bean requires destruction on shutdown. 1845 * <p>The default implementation checks the DisposableBean interface as well as 1846 * a specified destroy method and registered DestructionAwareBeanPostProcessors. 1847 * @param bean the bean instance to check 1848 * @param mbd the corresponding bean definition 1849 * @see org.springframework.beans.factory.DisposableBean 1850 * @see AbstractBeanDefinition#getDestroyMethodName() 1851 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor 1852 */ 1853 protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { 1854 return (bean.getClass() != NullBean.class && 1855 (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() && 1856 DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors())))); 1857 } 1858 1859 /** 1860 * Add the given bean to the list of disposable beans in this factory, 1861 * registering its DisposableBean interface and/or the given destroy method 1862 * to be called on factory shutdown (if applicable). Only applies to singletons. 1863 * @param beanName the name of the bean 1864 * @param bean the bean instance 1865 * @param mbd the bean definition for the bean 1866 * @see RootBeanDefinition#isSingleton 1867 * @see RootBeanDefinition#getDependsOn 1868 * @see #registerDisposableBean 1869 * @see #registerDependentBean 1870 */ 1871 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { 1872 AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null); 1873 if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { 1874 if (mbd.isSingleton()) { 1875 // Register a DisposableBean implementation that performs all destruction 1876 // work for the given bean: DestructionAwareBeanPostProcessors, 1877 // DisposableBean interface, custom destroy method. 1878 registerDisposableBean(beanName, 1879 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 1880 } 1881 else { 1882 // A bean with a custom scope... 1883 Scope scope = this.scopes.get(mbd.getScope()); 1884 if (scope == null) { 1885 throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); 1886 } 1887 scope.registerDestructionCallback(beanName, 1888 new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc)); 1889 } 1890 } 1891 } 1892 1893 1894 //--------------------------------------------------------------------- 1895 // Abstract methods to be implemented by subclasses 1896 //--------------------------------------------------------------------- 1897 1898 /** 1899 * Check if this bean factory contains a bean definition with the given name. 1900 * Does not consider any hierarchy this factory may participate in. 1901 * Invoked by {@code containsBean} when no cached singleton instance is found. 1902 * <p>Depending on the nature of the concrete bean factory implementation, 1903 * this operation might be expensive (for example, because of directory lookups 1904 * in external registries). However, for listable bean factories, this usually 1905 * just amounts to a local hash lookup: The operation is therefore part of the 1906 * public interface there. The same implementation can serve for both this 1907 * template method and the public interface method in that case. 1908 * @param beanName the name of the bean to look for 1909 * @return if this bean factory contains a bean definition with the given name 1910 * @see #containsBean 1911 * @see org.springframework.beans.factory.ListableBeanFactory#containsBeanDefinition 1912 */ 1913 protected abstract boolean containsBeanDefinition(String beanName); 1914 1915 /** 1916 * Return the bean definition for the given bean name. 1917 * Subclasses should normally implement caching, as this method is invoked 1918 * by this class every time bean definition metadata is needed. 1919 * <p>Depending on the nature of the concrete bean factory implementation, 1920 * this operation might be expensive (for example, because of directory lookups 1921 * in external registries). However, for listable bean factories, this usually 1922 * just amounts to a local hash lookup: The operation is therefore part of the 1923 * public interface there. The same implementation can serve for both this 1924 * template method and the public interface method in that case. 1925 * @param beanName the name of the bean to find a definition for 1926 * @return the BeanDefinition for this prototype name (never {@code null}) 1927 * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 1928 * if the bean definition cannot be resolved 1929 * @throws BeansException in case of errors 1930 * @see RootBeanDefinition 1931 * @see ChildBeanDefinition 1932 * @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition 1933 */ 1934 protected abstract BeanDefinition getBeanDefinition(String beanName) throws BeansException; 1935 1936 /** 1937 * Create a bean instance for the given merged bean definition (and arguments). 1938 * The bean definition will already have been merged with the parent definition 1939 * in case of a child definition. 1940 * <p>All bean retrieval methods delegate to this method for actual bean creation. 1941 * @param beanName the name of the bean 1942 * @param mbd the merged bean definition for the bean 1943 * @param args explicit arguments to use for constructor or factory method invocation 1944 * @return a new instance of the bean 1945 * @throws BeanCreationException if the bean could not be created 1946 */ 1947 protected abstract Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 1948 throws BeanCreationException; 1949 1950}