001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community 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 * http://www.opensource.org/licenses/ecl2.php 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 */ 016package org.kuali.rice.krad.datadictionary; 017 018import java.io.IOException; 019import java.io.NotSerializableException; 020import java.io.ObjectInputStream; 021import java.io.ObjectStreamException; 022import java.io.Serializable; 023import java.lang.annotation.Annotation; 024import java.lang.ref.Reference; 025import java.lang.ref.WeakReference; 026import java.lang.reflect.InvocationHandler; 027import java.lang.reflect.InvocationTargetException; 028import java.lang.reflect.Method; 029import java.lang.reflect.Proxy; 030import java.security.AccessController; 031import java.security.PrivilegedAction; 032import java.util.ArrayList; 033import java.util.Arrays; 034import java.util.Collection; 035import java.util.HashMap; 036import java.util.HashSet; 037import java.util.LinkedHashMap; 038import java.util.LinkedHashSet; 039import java.util.List; 040import java.util.Map; 041import java.util.Set; 042import java.util.concurrent.ConcurrentHashMap; 043 044import javax.inject.Provider; 045 046import org.springframework.beans.BeansException; 047import org.springframework.beans.FatalBeanException; 048import org.springframework.beans.TypeConverter; 049import org.springframework.beans.factory.BeanCreationException; 050import org.springframework.beans.factory.BeanCurrentlyInCreationException; 051import org.springframework.beans.factory.BeanDefinitionStoreException; 052import org.springframework.beans.factory.BeanFactory; 053import org.springframework.beans.factory.BeanFactoryAware; 054import org.springframework.beans.factory.BeanFactoryUtils; 055import org.springframework.beans.factory.CannotLoadBeanClassException; 056import org.springframework.beans.factory.FactoryBean; 057import org.springframework.beans.factory.NoSuchBeanDefinitionException; 058import org.springframework.beans.factory.NoUniqueBeanDefinitionException; 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.ConfigurableBeanFactory; 064import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 065import org.springframework.beans.factory.config.DependencyDescriptor; 066import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory; 067import org.springframework.beans.factory.support.AbstractBeanDefinition; 068import org.springframework.beans.factory.support.AutowireCandidateResolver; 069import org.springframework.beans.factory.support.BeanDefinitionRegistry; 070import org.springframework.beans.factory.support.BeanDefinitionValidationException; 071import org.springframework.beans.factory.support.RootBeanDefinition; 072import org.springframework.beans.factory.support.SimpleAutowireCandidateResolver; 073import org.springframework.core.annotation.AnnotationUtils; 074import org.springframework.util.Assert; 075import org.springframework.util.ObjectUtils; 076import org.springframework.util.StringUtils; 077 078/** 079 * Default implementation of the 080 * {@link org.springframework.beans.factory.ListableBeanFactory} and 081 * {@link BeanDefinitionRegistry} interfaces: a full-fledged bean factory 082 * based on bean definition objects. 083 * 084 * <p>Typical usage is registering all bean definitions first (possibly read 085 * from a bean definition file), before accessing beans. Bean definition lookup 086 * is therefore an inexpensive operation in a local bean definition table, 087 * operating on pre-built bean definition metadata objects. 088 * 089 * <p>Can be used as a standalone bean factory, or as a superclass for custom 090 * bean factories. Note that readers for specific bean definition formats are 091 * typically implemented separately rather than as bean factory subclasses: 092 * see for example {@link org.springframework.beans.factory.support.PropertiesBeanDefinitionReader} and 093 * {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}. 094 * 095 * <p>For an alternative implementation of the 096 * {@link org.springframework.beans.factory.ListableBeanFactory} interface, 097 * have a look at {@link org.springframework.beans.factory.support.StaticListableBeanFactory}, which manages existing 098 * bean instances rather than creating new ones based on bean definitions. 099 * 100 * <p>RICE Implementation note: This class, copied from Spring 3.2.3 contains the fix contributed for 101 * performance problem related to large Spring configuration sets. 102 * 103 * @author Rod Johnson 104 * @author Juergen Hoeller 105 * @author Sam Brannen 106 * @author Costin Leau 107 * @author Chris Beams 108 * @author Phillip Webb 109 * @since 16 April 2001 110 * @see org.springframework.beans.factory.support.StaticListableBeanFactory 111 * @see org.springframework.beans.factory.support.PropertiesBeanDefinitionReader 112 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader 113 */ 114@SuppressWarnings("serial") 115public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory 116 implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { 117 118 private static Class<?> javaxInjectProviderClass = null; 119 120 static { 121 ClassLoader cl = DefaultListableBeanFactory.class.getClassLoader(); 122 try { 123 javaxInjectProviderClass = cl.loadClass("javax.inject.Provider"); 124 } 125 catch (ClassNotFoundException ex) { 126 // JSR-330 API not available - Provider interface simply not supported then. 127 } 128 } 129 130 131 /** Map from serialized id to factory instance */ 132 private static final Map<String, Reference<DefaultListableBeanFactory>> serializableFactories = 133 new ConcurrentHashMap<String, Reference<DefaultListableBeanFactory>>(8); 134 135 /** Optional id for this factory, for serialization purposes */ 136 private String serializationId; 137 138 /** Whether to allow re-registration of a different definition with the same name */ 139 private boolean allowBeanDefinitionOverriding = true; 140 141 /** Whether to allow eager class loading even for lazy-init beans */ 142 private boolean allowEagerClassLoading = true; 143 144 /** Resolver to use for checking if a bean definition is an autowire candidate */ 145 private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver(); 146 147 /** Map from dependency type to corresponding autowired value */ 148 private final Map<Class<?>, Object> resolvableDependencies = new HashMap<Class<?>, Object>(16); 149 150 /** Map of bean definition objects, keyed by bean name */ 151 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64); 152 153 /** Map of singleton and non-singleton bean names keyed by dependency type */ 154 private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64); 155 156 /** Map of singleton-only bean names keyed by dependency type */ 157 private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64); 158 159 /** List of bean definition names, in registration order */ 160 private final List<String> beanDefinitionNames = new ArrayList<String>(); 161 162 /** Whether bean definition metadata may be cached for all beans */ 163 private boolean configurationFrozen = false; 164 165 /** Cached array of bean definition names in case of frozen configuration */ 166 private String[] frozenBeanDefinitionNames; 167 168 // Rice : performance fix for slow loading Spring context 169 private final Map<String,Set<String>> beanDefinitionsByParent = new ConcurrentHashMap<String, Set<String>>(); 170 // Rice : END performance fix for slow loading Spring context 171 172 /** 173 * Create a new DefaultListableBeanFactory. 174 */ 175 public DefaultListableBeanFactory() { 176 super(); 177 } 178 179 /** 180 * Create a new DefaultListableBeanFactory with the given parent. 181 * @param parentBeanFactory the parent BeanFactory 182 */ 183 public DefaultListableBeanFactory(BeanFactory parentBeanFactory) { 184 super(parentBeanFactory); 185 } 186 187 188 /** 189 * Specify an id for serialization purposes, allowing this BeanFactory to be 190 * deserialized from this id back into the BeanFactory object, if needed. 191 */ 192 public void setSerializationId(String serializationId) { 193 if (serializationId != null) { 194 serializableFactories.put(serializationId, new WeakReference<DefaultListableBeanFactory>(this)); 195 } 196 else if (this.serializationId != null) { 197 serializableFactories.remove(this.serializationId); 198 } 199 this.serializationId = serializationId; 200 } 201 202 /** 203 * Set whether it should be allowed to override bean definitions by registering 204 * a different definition with the same name, automatically replacing the former. 205 * If not, an exception will be thrown. This also applies to overriding aliases. 206 * <p>Default is "true". 207 * @see #registerBeanDefinition 208 */ 209 public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) { 210 this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding; 211 } 212 213 /** 214 * Set whether the factory is allowed to eagerly load bean classes 215 * even for bean definitions that are marked as "lazy-init". 216 * <p>Default is "true". Turn this flag off to suppress class loading 217 * for lazy-init beans unless such a bean is explicitly requested. 218 * In particular, by-type lookups will then simply ignore bean definitions 219 * without resolved class name, instead of loading the bean classes on 220 * demand just to perform a type check. 221 * @see org.springframework.beans.factory.support.AbstractBeanDefinition#setLazyInit 222 */ 223 public void setAllowEagerClassLoading(boolean allowEagerClassLoading) { 224 this.allowEagerClassLoading = allowEagerClassLoading; 225 } 226 227 /** 228 * Set a custom autowire candidate resolver for this BeanFactory to use 229 * when deciding whether a bean definition should be considered as a 230 * candidate for autowiring. 231 */ 232 public void setAutowireCandidateResolver(final AutowireCandidateResolver autowireCandidateResolver) { 233 Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null"); 234 if (autowireCandidateResolver instanceof BeanFactoryAware) { 235 if (System.getSecurityManager() != null) { 236 final BeanFactory target = this; 237 AccessController.doPrivileged(new PrivilegedAction<Object>() { 238 public Object run() { 239 ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target); 240 return null; 241 } 242 }, getAccessControlContext()); 243 } 244 else { 245 ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this); 246 } 247 } 248 this.autowireCandidateResolver = autowireCandidateResolver; 249 } 250 251 /** 252 * Return the autowire candidate resolver for this BeanFactory (never {@code null}). 253 */ 254 public AutowireCandidateResolver getAutowireCandidateResolver() { 255 return this.autowireCandidateResolver; 256 } 257 258 259 @Override 260 public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) { 261 super.copyConfigurationFrom(otherFactory); 262 if (otherFactory instanceof DefaultListableBeanFactory) { 263 DefaultListableBeanFactory otherListableFactory = (DefaultListableBeanFactory) otherFactory; 264 this.allowBeanDefinitionOverriding = otherListableFactory.allowBeanDefinitionOverriding; 265 this.allowEagerClassLoading = otherListableFactory.allowEagerClassLoading; 266 this.autowireCandidateResolver = otherListableFactory.autowireCandidateResolver; 267 this.resolvableDependencies.putAll(otherListableFactory.resolvableDependencies); 268 } 269 } 270 271 272 //--------------------------------------------------------------------- 273 // Implementation of ListableBeanFactory interface 274 //--------------------------------------------------------------------- 275 276 public <T> T getBean(Class<T> requiredType) throws BeansException { 277 Assert.notNull(requiredType, "Required type must not be null"); 278 String[] beanNames = getBeanNamesForType(requiredType); 279 if (beanNames.length > 1) { 280 ArrayList<String> autowireCandidates = new ArrayList<String>(); 281 for (String beanName : beanNames) { 282 if (getBeanDefinition(beanName).isAutowireCandidate()) { 283 autowireCandidates.add(beanName); 284 } 285 } 286 if (autowireCandidates.size() > 0) { 287 beanNames = autowireCandidates.toArray(new String[autowireCandidates.size()]); 288 } 289 } 290 if (beanNames.length == 1) { 291 return getBean(beanNames[0], requiredType); 292 } 293 else if (beanNames.length > 1) { 294 T primaryBean = null; 295 for (String beanName : beanNames) { 296 T beanInstance = getBean(beanName, requiredType); 297 if (isPrimary(beanName, beanInstance)) { 298 if (primaryBean != null) { 299 throw new NoUniqueBeanDefinitionException(requiredType, beanNames.length, 300 "more than one 'primary' bean found of required type: " + Arrays.asList(beanNames)); 301 } 302 primaryBean = beanInstance; 303 } 304 } 305 if (primaryBean != null) { 306 return primaryBean; 307 } 308 throw new NoUniqueBeanDefinitionException(requiredType, beanNames); 309 } 310 else if (getParentBeanFactory() != null) { 311 return getParentBeanFactory().getBean(requiredType); 312 } 313 else { 314 throw new NoSuchBeanDefinitionException(requiredType); 315 } 316 } 317 318 @Override 319 public boolean containsBeanDefinition(String beanName) { 320 Assert.notNull(beanName, "Bean name must not be null"); 321 return this.beanDefinitionMap.containsKey(beanName); 322 } 323 324 public int getBeanDefinitionCount() { 325 return this.beanDefinitionMap.size(); 326 } 327 328 public String[] getBeanDefinitionNames() { 329 synchronized (this.beanDefinitionMap) { 330 if (this.frozenBeanDefinitionNames != null) { 331 return this.frozenBeanDefinitionNames; 332 } 333 else { 334 return StringUtils.toStringArray(this.beanDefinitionNames); 335 } 336 } 337 } 338 339 public String[] getBeanNamesForType(Class<?> type) { 340 return getBeanNamesForType(type, true, true); 341 } 342 343 public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { 344 if (!isConfigurationFrozen() || type == null || !allowEagerInit) { 345 return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit); 346 } 347 Map<Class<?>, String[]> cache = 348 (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType); 349 String[] resolvedBeanNames = cache.get(type); 350 if (resolvedBeanNames != null) { 351 return resolvedBeanNames; 352 } 353 resolvedBeanNames = doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit); 354 cache.put(type, resolvedBeanNames); 355 return resolvedBeanNames; 356 } 357 358 private String[] doGetBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { 359 List<String> result = new ArrayList<String>(); 360 361 // Check all bean definitions. 362 String[] beanDefinitionNames = getBeanDefinitionNames(); 363 for (String beanName : beanDefinitionNames) { 364 // Only consider bean as eligible if the bean name 365 // is not defined as alias for some other bean. 366 if (!isAlias(beanName)) { 367 try { 368 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 369 // Only check bean definition if it is complete. 370 if (!mbd.isAbstract() && (allowEagerInit || 371 ((mbd.hasBeanClass() || !mbd.isLazyInit() || this.allowEagerClassLoading)) && 372 !requiresEagerInitForType(mbd.getFactoryBeanName()))) { 373 // In case of FactoryBean, match object created by FactoryBean. 374 boolean isFactoryBean = isFactoryBean(beanName, mbd); 375 boolean matchFound = (allowEagerInit || !isFactoryBean || containsSingleton(beanName)) && 376 (includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type); 377 if (!matchFound && isFactoryBean) { 378 // In case of FactoryBean, try to match FactoryBean instance itself next. 379 beanName = FACTORY_BEAN_PREFIX + beanName; 380 matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type); 381 } 382 if (matchFound) { 383 result.add(beanName); 384 } 385 } 386 } 387 catch (CannotLoadBeanClassException ex) { 388 if (allowEagerInit) { 389 throw ex; 390 } 391 // Probably contains a placeholder: let's ignore it for type matching purposes. 392 if (this.logger.isDebugEnabled()) { 393 this.logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex); 394 } 395 onSuppressedException(ex); 396 } 397 catch (BeanDefinitionStoreException ex) { 398 if (allowEagerInit) { 399 throw ex; 400 } 401 // Probably contains a placeholder: let's ignore it for type matching purposes. 402 if (this.logger.isDebugEnabled()) { 403 this.logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex); 404 } 405 onSuppressedException(ex); 406 } 407 } 408 } 409 410 // Check singletons too, to catch manually registered singletons. 411 String[] singletonNames = getSingletonNames(); 412 for (String beanName : singletonNames) { 413 // Only check if manually registered. 414 if (!containsBeanDefinition(beanName)) { 415 // In case of FactoryBean, match object created by FactoryBean. 416 if (isFactoryBean(beanName)) { 417 if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) { 418 result.add(beanName); 419 // Match found for this bean: do not match FactoryBean itself anymore. 420 continue; 421 } 422 // In case of FactoryBean, try to match FactoryBean itself next. 423 beanName = FACTORY_BEAN_PREFIX + beanName; 424 } 425 // Match raw bean instance (might be raw FactoryBean). 426 if (isTypeMatch(beanName, type)) { 427 result.add(beanName); 428 } 429 } 430 } 431 432 return StringUtils.toStringArray(result); 433 } 434 435 /** 436 * Check whether the specified bean would need to be eagerly initialized 437 * in order to determine its type. 438 * @param factoryBeanName a factory-bean reference that the bean definition 439 * defines a factory method for 440 * @return whether eager initialization is necessary 441 */ 442 private boolean requiresEagerInitForType(String factoryBeanName) { 443 return (factoryBeanName != null && isFactoryBean(factoryBeanName) && !containsSingleton(factoryBeanName)); 444 } 445 446 public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException { 447 return getBeansOfType(type, true, true); 448 } 449 450 public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) 451 throws BeansException { 452 453 String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit); 454 Map<String, T> result = new LinkedHashMap<String, T>(beanNames.length); 455 for (String beanName : beanNames) { 456 try { 457 result.put(beanName, getBean(beanName, type)); 458 } 459 catch (BeanCreationException ex) { 460 Throwable rootCause = ex.getMostSpecificCause(); 461 if (rootCause instanceof BeanCurrentlyInCreationException) { 462 BeanCreationException bce = (BeanCreationException) rootCause; 463 if (isCurrentlyInCreation(bce.getBeanName())) { 464 if (this.logger.isDebugEnabled()) { 465 this.logger.debug("Ignoring match to currently created bean '" + beanName + "': " + 466 ex.getMessage()); 467 } 468 onSuppressedException(ex); 469 // Ignore: indicates a circular reference when autowiring constructors. 470 // We want to find matches other than the currently created bean itself. 471 continue; 472 } 473 } 474 throw ex; 475 } 476 } 477 return result; 478 } 479 480 public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) { 481 Set<String> beanNames = new LinkedHashSet<String>(getBeanDefinitionCount()); 482 beanNames.addAll(Arrays.asList(getBeanDefinitionNames())); 483 beanNames.addAll(Arrays.asList(getSingletonNames())); 484 Map<String, Object> results = new LinkedHashMap<String, Object>(); 485 for (String beanName : beanNames) { 486 if (findAnnotationOnBean(beanName, annotationType) != null) { 487 results.put(beanName, getBean(beanName)); 488 } 489 } 490 return results; 491 } 492 493 /** 494 * Find a {@link Annotation} of {@code annotationType} on the specified 495 * bean, traversing its interfaces and super classes if no annotation can be 496 * found on the given class itself, as well as checking its raw bean class 497 * if not found on the exposed bean reference (e.g. in case of a proxy). 498 */ 499 public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) { 500 A ann = null; 501 Class<?> beanType = getType(beanName); 502 if (beanType != null) { 503 ann = AnnotationUtils.findAnnotation(beanType, annotationType); 504 } 505 if (ann == null && containsBeanDefinition(beanName)) { 506 BeanDefinition bd = getMergedBeanDefinition(beanName); 507 if (bd instanceof AbstractBeanDefinition) { 508 AbstractBeanDefinition abd = (AbstractBeanDefinition) bd; 509 if (abd.hasBeanClass()) { 510 ann = AnnotationUtils.findAnnotation(abd.getBeanClass(), annotationType); 511 } 512 } 513 } 514 return ann; 515 } 516 517 518 //--------------------------------------------------------------------- 519 // Implementation of ConfigurableListableBeanFactory interface 520 //--------------------------------------------------------------------- 521 522 public void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue) { 523 Assert.notNull(dependencyType, "Type must not be null"); 524 if (autowiredValue != null) { 525 Assert.isTrue((autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue)), 526 "Value [" + autowiredValue + "] does not implement specified type [" + dependencyType.getName() + "]"); 527 this.resolvableDependencies.put(dependencyType, autowiredValue); 528 } 529 } 530 531 public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) 532 throws NoSuchBeanDefinitionException { 533 534 // Consider FactoryBeans as autowiring candidates. 535 boolean isFactoryBean = (descriptor != null && descriptor.getDependencyType() != null && 536 FactoryBean.class.isAssignableFrom(descriptor.getDependencyType())); 537 if (isFactoryBean) { 538 beanName = BeanFactoryUtils.transformedBeanName(beanName); 539 } 540 541 if (containsBeanDefinition(beanName)) { 542 return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanName), descriptor); 543 } 544 else if (containsSingleton(beanName)) { 545 return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor); 546 } 547 else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) { 548 // No bean definition found in this factory -> delegate to parent. 549 return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor); 550 } 551 else { 552 return true; 553 } 554 } 555 556 /** 557 * Determine whether the specified bean definition qualifies as an autowire candidate, 558 * to be injected into other beans which declare a dependency of matching type. 559 * @param beanName the name of the bean definition to check 560 * @param mbd the merged bean definition to check 561 * @param descriptor the descriptor of the dependency to resolve 562 * @return whether the bean should be considered as autowire candidate 563 */ 564 protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor) { 565 resolveBeanClass(mbd, beanName); 566 567 // Rice : removing code due to package restrictions, not used in dictionary 568// if (mbd.isFactoryMethodUnique) { 569// boolean resolve; 570// synchronized (mbd.constructorArgumentLock) { 571// resolve = (mbd.resolvedConstructorOrFactoryMethod == null); 572// } 573// if (resolve) { 574// new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd); 575// } 576// } 577 // Rice : end code removal 578 579 return getAutowireCandidateResolver().isAutowireCandidate( 580 new BeanDefinitionHolder(mbd, beanName, getAliases(beanName)), descriptor); 581 } 582 583 @Override 584 public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { 585 BeanDefinition bd = this.beanDefinitionMap.get(beanName); 586 if (bd == null) { 587 if (this.logger.isTraceEnabled()) { 588 this.logger.trace("No bean named '" + beanName + "' found in " + this); 589 } 590 throw new NoSuchBeanDefinitionException(beanName); 591 } 592 return bd; 593 } 594 595 public void freezeConfiguration() { 596 this.configurationFrozen = true; 597 synchronized (this.beanDefinitionMap) { 598 this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames); 599 } 600 } 601 602 public boolean isConfigurationFrozen() { 603 return this.configurationFrozen; 604 } 605 606 /** 607 * Considers all beans as eligible for metadata caching 608 * if the factory's configuration has been marked as frozen. 609 * @see #freezeConfiguration() 610 */ 611 @Override 612 protected boolean isBeanEligibleForMetadataCaching(String beanName) { 613 return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName)); 614 } 615 616 public void preInstantiateSingletons() throws BeansException { 617 if (this.logger.isTraceEnabled()) { 618 this.logger.info("Pre-instantiating singletons in " + this); 619 } else if (this.logger.isInfoEnabled()) { 620 this.logger.info("Pre-instantiating singletons"); 621 } 622 List<String> beanNames; 623 synchronized (this.beanDefinitionMap) { 624 // Iterate over a copy to allow for init methods which in turn register new bean definitions. 625 // While this may not be part of the regular factory bootstrap, it does otherwise work fine. 626 beanNames = new ArrayList<String>(this.beanDefinitionNames); 627 } 628 for (String beanName : beanNames) { 629 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); 630 if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { 631 if (isFactoryBean(beanName)) { 632 final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); 633 boolean isEagerInit; 634 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { 635 isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { 636 public Boolean run() { 637 return ((SmartFactoryBean<?>) factory).isEagerInit(); 638 } 639 }, getAccessControlContext()); 640 } 641 else { 642 isEagerInit = (factory instanceof SmartFactoryBean && 643 ((SmartFactoryBean<?>) factory).isEagerInit()); 644 } 645 if (isEagerInit) { 646 getBean(beanName); 647 } 648 } 649 else { 650 getBean(beanName); 651 } 652 } 653 } 654 } 655 656 657 //--------------------------------------------------------------------- 658 // Implementation of BeanDefinitionRegistry interface 659 //--------------------------------------------------------------------- 660 661 public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) 662 throws BeanDefinitionStoreException { 663 664 Assert.hasText(beanName, "Bean name must not be empty"); 665 Assert.notNull(beanDefinition, "BeanDefinition must not be null"); 666 667 if (beanDefinition instanceof AbstractBeanDefinition) { 668 try { 669 ((AbstractBeanDefinition) beanDefinition).validate(); 670 } 671 catch (BeanDefinitionValidationException ex) { 672 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, 673 "Validation of bean definition failed", ex); 674 } 675 } 676 677 synchronized (this.beanDefinitionMap) { 678 Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); 679 if (oldBeanDefinition != null) { 680 if (!this.allowBeanDefinitionOverriding) { 681 throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, 682 "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + 683 "': There is already [" + oldBeanDefinition + "] bound."); 684 } 685 else { 686 if (this.logger.isInfoEnabled()) { 687 this.logger.info("Overriding bean definition for bean '" + beanName + 688 "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); 689 } 690 } 691 } 692 else { 693 this.beanDefinitionNames.add(beanName); 694 this.frozenBeanDefinitionNames = null; 695 } 696 this.beanDefinitionMap.put(beanName, beanDefinition); 697 } 698 699 resetBeanDefinition(beanName); 700 } 701 702 public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { 703 Assert.hasText(beanName, "'beanName' must not be empty"); 704 705 synchronized (this.beanDefinitionMap) { 706 BeanDefinition bd = this.beanDefinitionMap.remove(beanName); 707 if (bd == null) { 708 if (this.logger.isTraceEnabled()) { 709 this.logger.trace("No bean named '" + beanName + "' found in " + this); 710 } 711 throw new NoSuchBeanDefinitionException(beanName); 712 } 713 this.beanDefinitionNames.remove(beanName); 714 this.frozenBeanDefinitionNames = null; 715 // Rice : performance fix for slow loading Spring context 716 // Pull it out of the parent map 717 if ( StringUtils.hasText( bd.getParentName() ) ) { 718 if ( beanDefinitionsByParent.get(bd.getParentName()) != null ) { 719 beanDefinitionsByParent.get(bd.getParentName()).remove(beanName); 720 } 721 } 722 // Rice : END performance fix for slow loading Spring context 723 } 724 725 resetBeanDefinition(beanName); 726 } 727 728 /** 729 * Reset all bean definition caches for the given bean, 730 * including the caches of beans that are derived from it. 731 * @param beanName the name of the bean to reset 732 */ 733 protected void resetBeanDefinition(String beanName) { 734 // Remove the merged bean definition for the given bean, if already created. 735 clearMergedBeanDefinition(beanName); 736 737 // Remove corresponding bean from singleton cache, if any. Shouldn't usually 738 // be necessary, rather just meant for overriding a context's default beans 739 // (e.g. the default StaticMessageSource in a StaticApplicationContext). 740 destroySingleton(beanName); 741 742 // Remove any assumptions about by-type mappings. 743 clearByTypeCache(); 744 745 // Reset all bean definitions that have the given bean as parent (recursively). 746 // Rice : performance fix for slow loading Spring context 747 Set<String> childBeans = beanDefinitionsByParent.get(beanName); 748 if ( childBeans != null ) { 749 for ( String childBeanName : childBeans ) { 750 resetBeanDefinition(childBeanName); 751 } 752 } 753 // Rice: Existing code was O(n!), since the bean definition names list keeps getting longer 754// for (String bdName : this.beanDefinitionNames) { 755// if (!beanName.equals(bdName)) { 756// BeanDefinition bd = this.beanDefinitionMap.get(bdName); 757// if (beanName.equals(bd.getParentName())) { 758// resetBeanDefinition(bdName); 759// } 760// } 761// } 762 // Rice : END performance fix for slow loading Spring context 763 } 764 765 // Rice : performance fix for slow loading Spring context 766 protected void addBeanToParentMap( String parentName, String beanName ) { 767 Set<String> defs = beanDefinitionsByParent.get(parentName); 768 if ( defs == null ) { 769 defs = new HashSet<String>(); 770 beanDefinitionsByParent.put(parentName, defs); 771 } 772 defs.add(beanName); 773 } 774 // Rice : END performance fix for slow loading Spring context 775 776 /** 777 * Only allows alias overriding if bean definition overriding is allowed. 778 */ 779 @Override 780 protected boolean allowAliasOverriding() { 781 return this.allowBeanDefinitionOverriding; 782 } 783 784 @Override 785 public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { 786 super.registerSingleton(beanName, singletonObject); 787 clearByTypeCache(); 788 } 789 790 @Override 791 public void destroySingleton(String beanName) { 792 super.destroySingleton(beanName); 793 clearByTypeCache(); 794 } 795 796 /** 797 * Remove any assumptions about by-type mappings. 798 */ 799 private void clearByTypeCache() { 800 this.allBeanNamesByType.clear(); 801 this.singletonBeanNamesByType.clear(); 802 } 803 804 805 //--------------------------------------------------------------------- 806 // Dependency resolution functionality 807 //--------------------------------------------------------------------- 808 809 public Object resolveDependency(DependencyDescriptor descriptor, String beanName, 810 Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { 811 812 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); 813 if (descriptor.getDependencyType().equals(ObjectFactory.class)) { 814 return new DependencyObjectFactory(descriptor, beanName); 815 } 816 else if (descriptor.getDependencyType().equals(javaxInjectProviderClass)) { 817 return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName); 818 } 819 else { 820 return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter); 821 } 822 } 823 824 protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName, 825 Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { 826 827 Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); 828 if (value != null) { 829 if (value instanceof String) { 830 String strVal = resolveEmbeddedValue((String) value); 831 BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); 832 value = evaluateBeanDefinitionString(strVal, bd); 833 } 834 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 835 return (descriptor.getField() != null ? 836 converter.convertIfNecessary(value, type, descriptor.getField()) : 837 converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); 838 } 839 840 if (type.isArray()) { 841 Class<?> componentType = type.getComponentType(); 842 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor); 843 if (matchingBeans.isEmpty()) { 844 if (descriptor.isRequired()) { 845 raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor); 846 } 847 return null; 848 } 849 if (autowiredBeanNames != null) { 850 autowiredBeanNames.addAll(matchingBeans.keySet()); 851 } 852 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 853 return converter.convertIfNecessary(matchingBeans.values(), type); 854 } 855 else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { 856 Class<?> elementType = descriptor.getCollectionType(); 857 if (elementType == null) { 858 if (descriptor.isRequired()) { 859 throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]"); 860 } 861 return null; 862 } 863 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor); 864 if (matchingBeans.isEmpty()) { 865 if (descriptor.isRequired()) { 866 raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor); 867 } 868 return null; 869 } 870 if (autowiredBeanNames != null) { 871 autowiredBeanNames.addAll(matchingBeans.keySet()); 872 } 873 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); 874 return converter.convertIfNecessary(matchingBeans.values(), type); 875 } 876 else if (Map.class.isAssignableFrom(type) && type.isInterface()) { 877 Class<?> keyType = descriptor.getMapKeyType(); 878 if (keyType == null || !String.class.isAssignableFrom(keyType)) { 879 if (descriptor.isRequired()) { 880 throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() + 881 "] must be assignable to [java.lang.String]"); 882 } 883 return null; 884 } 885 Class<?> valueType = descriptor.getMapValueType(); 886 if (valueType == null) { 887 if (descriptor.isRequired()) { 888 throw new FatalBeanException("No value type declared for map [" + type.getName() + "]"); 889 } 890 return null; 891 } 892 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); 893 if (matchingBeans.isEmpty()) { 894 if (descriptor.isRequired()) { 895 raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); 896 } 897 return null; 898 } 899 if (autowiredBeanNames != null) { 900 autowiredBeanNames.addAll(matchingBeans.keySet()); 901 } 902 return matchingBeans; 903 } 904 else { 905 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); 906 if (matchingBeans.isEmpty()) { 907 if (descriptor.isRequired()) { 908 raiseNoSuchBeanDefinitionException(type, "", descriptor); 909 } 910 return null; 911 } 912 if (matchingBeans.size() > 1) { 913 String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor); 914 if (primaryBeanName == null) { 915 throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); 916 } 917 if (autowiredBeanNames != null) { 918 autowiredBeanNames.add(primaryBeanName); 919 } 920 return matchingBeans.get(primaryBeanName); 921 } 922 // We have exactly one match. 923 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); 924 if (autowiredBeanNames != null) { 925 autowiredBeanNames.add(entry.getKey()); 926 } 927 return entry.getValue(); 928 } 929 } 930 931 /** 932 * Find bean instances that match the required type. 933 * Called during autowiring for the specified bean. 934 * @param beanName the name of the bean that is about to be wired 935 * @param requiredType the actual type of bean to look for 936 * (may be an array component type or collection element type) 937 * @param descriptor the descriptor of the dependency to resolve 938 * @return a Map of candidate names and candidate instances that match 939 * the required type (never {@code null}) 940 * @throws BeansException in case of errors 941 * @see #autowireByType 942 * @see #autowireConstructor 943 */ 944 protected Map<String, Object> findAutowireCandidates( 945 String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { 946 947 String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( 948 this, requiredType, true, descriptor.isEager()); 949 Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length); 950 for (Class<?> autowiringType : this.resolvableDependencies.keySet()) { 951 if (autowiringType.isAssignableFrom(requiredType)) { 952 Object autowiringValue = this.resolvableDependencies.get(autowiringType); 953 autowiringValue = resolveAutowiringValue(autowiringValue, requiredType); 954 if (requiredType.isInstance(autowiringValue)) { 955 result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue); 956 break; 957 } 958 } 959 } 960 for (String candidateName : candidateNames) { 961 if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) { 962 result.put(candidateName, getBean(candidateName)); 963 } 964 } 965 return result; 966 } 967 968 // Rice : copying code from AutowireUtils due to package restrictions 969 protected static Object resolveAutowiringValue(Object autowiringValue, Class requiredType) { 970 if (autowiringValue instanceof ObjectFactory && !requiredType.isInstance(autowiringValue)) { 971 ObjectFactory factory = (ObjectFactory) autowiringValue; 972 if (autowiringValue instanceof Serializable && requiredType.isInterface()) { 973 autowiringValue = Proxy.newProxyInstance(requiredType.getClassLoader(), new Class[]{requiredType}, 974 new ObjectFactoryDelegatingInvocationHandler(factory)); 975 } 976 else { 977 return factory.getObject(); 978 } 979 } 980 return autowiringValue; 981 } 982 983 /** 984 * Reflective InvocationHandler for lazy access to the current target object. 985 */ 986 private static class ObjectFactoryDelegatingInvocationHandler implements InvocationHandler, Serializable { 987 988 private final ObjectFactory objectFactory; 989 990 public ObjectFactoryDelegatingInvocationHandler(ObjectFactory objectFactory) { 991 this.objectFactory = objectFactory; 992 } 993 994 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 995 String methodName = method.getName(); 996 if (methodName.equals("equals")) { 997 // Only consider equal when proxies are identical. 998 return (proxy == args[0]); 999 } 1000 else if (methodName.equals("hashCode")) { 1001 // Use hashCode of proxy. 1002 return System.identityHashCode(proxy); 1003 } 1004 else if (methodName.equals("toString")) { 1005 return this.objectFactory.toString(); 1006 } 1007 try { 1008 return method.invoke(this.objectFactory.getObject(), args); 1009 } 1010 catch (InvocationTargetException ex) { 1011 throw ex.getTargetException(); 1012 } 1013 } 1014 } 1015 // Rice : end code copy 1016 1017 /** 1018 * Determine the primary autowire candidate in the given set of beans. 1019 * @param candidateBeans a Map of candidate names and candidate instances 1020 * that match the required type, as returned by {@link #findAutowireCandidates} 1021 * @param descriptor the target dependency to match against 1022 * @return the name of the primary candidate, or {@code null} if none found 1023 */ 1024 protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, DependencyDescriptor descriptor) { 1025 String primaryBeanName = null; 1026 String fallbackBeanName = null; 1027 for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) { 1028 String candidateBeanName = entry.getKey(); 1029 Object beanInstance = entry.getValue(); 1030 if (isPrimary(candidateBeanName, beanInstance)) { 1031 if (primaryBeanName != null) { 1032 boolean candidateLocal = containsBeanDefinition(candidateBeanName); 1033 boolean primaryLocal = containsBeanDefinition(primaryBeanName); 1034 if (candidateLocal == primaryLocal) { 1035 throw new NoUniqueBeanDefinitionException(descriptor.getDependencyType(), candidateBeans.size(), 1036 "more than one 'primary' bean found among candidates: " + candidateBeans.keySet()); 1037 } 1038 else if (candidateLocal && !primaryLocal) { 1039 primaryBeanName = candidateBeanName; 1040 } 1041 } 1042 else { 1043 primaryBeanName = candidateBeanName; 1044 } 1045 } 1046 if (primaryBeanName == null && 1047 (this.resolvableDependencies.values().contains(beanInstance) || 1048 matchesBeanName(candidateBeanName, descriptor.getDependencyName()))) { 1049 fallbackBeanName = candidateBeanName; 1050 } 1051 } 1052 return (primaryBeanName != null ? primaryBeanName : fallbackBeanName); 1053 } 1054 1055 /** 1056 * Return whether the bean definition for the given bean name has been 1057 * marked as a primary bean. 1058 * @param beanName the name of the bean 1059 * @param beanInstance the corresponding bean instance 1060 * @return whether the given bean qualifies as primary 1061 */ 1062 protected boolean isPrimary(String beanName, Object beanInstance) { 1063 if (containsBeanDefinition(beanName)) { 1064 return getMergedLocalBeanDefinition(beanName).isPrimary(); 1065 } 1066 BeanFactory parentFactory = getParentBeanFactory(); 1067 return (parentFactory instanceof DefaultListableBeanFactory && 1068 ((DefaultListableBeanFactory) parentFactory).isPrimary(beanName, beanInstance)); 1069 } 1070 1071 /** 1072 * Determine whether the given candidate name matches the bean name or the aliases 1073 * stored in this bean definition. 1074 */ 1075 protected boolean matchesBeanName(String beanName, String candidateName) { 1076 return (candidateName != null && 1077 (candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName))); 1078 } 1079 1080 /** 1081 * Raise a NoSuchBeanDefinitionException for an unresolvable dependency. 1082 */ 1083 private void raiseNoSuchBeanDefinitionException( 1084 Class<?> type, String dependencyDescription, DependencyDescriptor descriptor) 1085 throws NoSuchBeanDefinitionException { 1086 1087 throw new NoSuchBeanDefinitionException(type, dependencyDescription, 1088 "expected at least 1 bean which qualifies as autowire candidate for this dependency. " + 1089 "Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations())); 1090 } 1091 1092 1093 @Override 1094 public String toString() { 1095 StringBuilder sb = new StringBuilder(ObjectUtils.identityToString(this)); 1096 sb.append(": defining beans ["); 1097 sb.append(StringUtils.arrayToCommaDelimitedString(getBeanDefinitionNames())); 1098 sb.append("]; "); 1099 BeanFactory parent = getParentBeanFactory(); 1100 if (parent == null) { 1101 sb.append("root of factory hierarchy"); 1102 } 1103 else { 1104 sb.append("parent: ").append(ObjectUtils.identityToString(parent)); 1105 } 1106 return sb.toString(); 1107 } 1108 1109 1110 //--------------------------------------------------------------------- 1111 // Serialization support 1112 //--------------------------------------------------------------------- 1113 1114 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { 1115 throw new NotSerializableException("DefaultListableBeanFactory itself is not deserializable - " + 1116 "just a SerializedBeanFactoryReference is"); 1117 } 1118 1119 protected Object writeReplace() throws ObjectStreamException { 1120 if (this.serializationId != null) { 1121 return new SerializedBeanFactoryReference(this.serializationId); 1122 } 1123 else { 1124 throw new NotSerializableException("DefaultListableBeanFactory has no serialization id"); 1125 } 1126 } 1127 1128 1129 /** 1130 * Minimal id reference to the factory. 1131 * Resolved to the actual factory instance on deserialization. 1132 */ 1133 private static class SerializedBeanFactoryReference implements Serializable { 1134 1135 private final String id; 1136 1137 public SerializedBeanFactoryReference(String id) { 1138 this.id = id; 1139 } 1140 1141 private Object readResolve() { 1142 Reference<?> ref = serializableFactories.get(this.id); 1143 if (ref == null) { 1144 throw new IllegalStateException( 1145 "Cannot deserialize BeanFactory with id " + this.id + ": no factory registered for this id"); 1146 } 1147 Object result = ref.get(); 1148 if (result == null) { 1149 throw new IllegalStateException( 1150 "Cannot deserialize BeanFactory with id " + this.id + ": factory has been garbage-collected"); 1151 } 1152 return result; 1153 } 1154 } 1155 1156 1157 /** 1158 * Serializable ObjectFactory for lazy resolution of a dependency. 1159 */ 1160 private class DependencyObjectFactory implements ObjectFactory<Object>, Serializable { 1161 1162 private final DependencyDescriptor descriptor; 1163 1164 private final String beanName; 1165 1166 public DependencyObjectFactory(DependencyDescriptor descriptor, String beanName) { 1167 this.descriptor = new DependencyDescriptor(descriptor); 1168 this.descriptor.increaseNestingLevel(); 1169 this.beanName = beanName; 1170 } 1171 1172 public Object getObject() throws BeansException { 1173 return doResolveDependency(this.descriptor, this.descriptor.getDependencyType(), this.beanName, null, null); 1174 } 1175 } 1176 1177 1178 /** 1179 * Serializable ObjectFactory for lazy resolution of a dependency. 1180 */ 1181 private class DependencyProvider extends DependencyObjectFactory implements Provider<Object> { 1182 1183 public DependencyProvider(DependencyDescriptor descriptor, String beanName) { 1184 super(descriptor, beanName); 1185 } 1186 1187 public Object get() throws BeansException { 1188 return getObject(); 1189 } 1190 } 1191 1192 1193 /** 1194 * Separate inner class for avoiding a hard dependency on the {@code javax.inject} API. 1195 */ 1196 private class DependencyProviderFactory { 1197 1198 public Object createDependencyProvider(DependencyDescriptor descriptor, String beanName) { 1199 return new DependencyProvider(descriptor, beanName); 1200 } 1201 } 1202 1203} 1204