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