diff options
author | Emmanuel Bourg <ebourg@apache.org> | 2015-07-15 23:21:27 +0200 |
---|---|---|
committer | Emmanuel Bourg <ebourg@apache.org> | 2015-07-15 23:21:27 +0200 |
commit | da46d30e80e4c59a41cf52055d06faa1dbb7e383 (patch) | |
tree | 52b707fbbccd5b6100088913f32c1cbd00568790 /spring-beans/src/main/java/org/springframework/beans/factory/support | |
parent | c03c348db4e91c613982cbe6c99d0cf04ea14fe3 (diff) |
Imported Upstream version 4.0.9
Diffstat (limited to 'spring-beans/src/main/java/org/springframework/beans/factory/support')
34 files changed, 811 insertions, 344 deletions
diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index f1bbf032..b0525263 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -68,8 +68,8 @@ import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor; import org.springframework.beans.factory.config.TypedStringValue; +import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.GenericTypeResolver; -import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.PriorityOrdered; @@ -120,7 +120,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy(); /** Resolver strategy for method parameter names */ - private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer(); + private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); /** Whether to automatically try to resolve circular references between beans */ private boolean allowCircularReferences = true; @@ -191,7 +191,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac /** * Set the ParameterNameDiscoverer to use for resolving method parameter * names if needed (e.g. for constructor names). - * <p>The default is {@link LocalVariableTableParameterNameDiscoverer}. + * <p>Default is a {@link DefaultParameterNameDiscoverer}. */ public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) { this.parameterNameDiscoverer = parameterNameDiscoverer; @@ -280,6 +280,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac // Typical methods for creating and populating external bean instances //------------------------------------------------------------------------- + @Override @SuppressWarnings("unchecked") public <T> T createBean(Class<T> beanClass) throws BeansException { // Use prototype bean definition, to avoid registering bean as dependent bean. @@ -289,6 +290,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return (T) createBean(beanClass.getName(), bd, null); } + @Override public void autowireBean(Object existingBean) { // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(ClassUtils.getUserClass(existingBean)); @@ -299,6 +301,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac populateBean(bd.getBeanClass().getName(), bd, bw); } + @Override public Object configureBean(Object existingBean, String beanName) throws BeansException { markBeanAsCreated(beanName); BeanDefinition mbd = getMergedBeanDefinition(beanName); @@ -320,6 +323,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return initializeBean(beanName, existingBean, bd); } + @Override public Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException { return resolveDependency(descriptor, beanName, null, null); } @@ -329,6 +333,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac // Specialized methods for fine-grained control over the bean lifecycle //------------------------------------------------------------------------- + @Override public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException { // Use non-singleton bean definition, to avoid registering bean as dependent bean. RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck); @@ -336,6 +341,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return createBean(beanClass.getName(), bd, null); } + @Override public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException { // Use non-singleton bean definition, to avoid registering bean as dependent bean. final RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck); @@ -348,6 +354,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac final BeanFactory parent = this; if (System.getSecurityManager() != null) { bean = AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { return getInstantiationStrategy().instantiate(bd, null, parent); } @@ -361,6 +368,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac } } + @Override public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException { @@ -376,6 +384,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac populateBean(bd.getBeanClass().getName(), bd, bw); } + @Override public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException { markBeanAsCreated(beanName); BeanDefinition bd = getMergedBeanDefinition(beanName); @@ -384,10 +393,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac applyPropertyValues(beanName, bd, bw, bd.getPropertyValues()); } + @Override public Object initializeBean(Object existingBean, String beanName) { return initializeBean(beanName, existingBean, null); } + @Override public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { @@ -401,6 +412,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return result; } + @Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { @@ -414,6 +426,11 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac return result; } + @Override + public void destroyBean(Object existingBean) { + new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy(); + } + //--------------------------------------------------------------------- // Implementation of relevant AbstractBeanFactory template methods @@ -507,6 +524,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { + @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } @@ -609,7 +627,12 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac * @return the type for the bean if determinable, or {@code null} else * @see #createBean */ - protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) { + protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class<?>... typesToMatch) { + Class<?> preResolved = mbd.resolvedFactoryMethodReturnType; + if (preResolved != null) { + return preResolved; + } + Class<?> factoryClass; boolean isStatic = true; @@ -635,6 +658,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac // If all factory methods have the same return type, return that type. // Can't clearly figure out exact method due to type converting / autowiring! Class<?> commonType = null; + boolean cache = false; int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount(); Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass); for (Method factoryMethod : candidates) { @@ -669,6 +693,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac Class<?> returnType = AutowireUtils.resolveReturnTypeForFactoryMethod( factoryMethod, args, getBeanClassLoader()); if (returnType != null) { + cache = true; commonType = ClassUtils.determineCommonAncestor(returnType, commonType); } } @@ -686,6 +711,9 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (commonType != null) { // Clear return type found: all factory methods return same type. + if (cache) { + mbd.resolvedFactoryMethodReturnType = commonType; + } return commonType; } else { @@ -712,27 +740,36 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac String factoryBeanName = mbd.getFactoryBeanName(); final String factoryMethodName = mbd.getFactoryMethodName(); - if (factoryBeanName != null && factoryMethodName != null) { - // Try to obtain the FactoryBean's object type without instantiating it at all. - BeanDefinition fbDef = getBeanDefinition(factoryBeanName); - if (fbDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) fbDef).hasBeanClass()) { - // CGLIB subclass methods hide generic parameters; look at the original user class. - Class<?> fbClass = ClassUtils.getUserClass(((AbstractBeanDefinition) fbDef).getBeanClass()); - // Find the given factory method, taking into account that in the case of - // @Bean methods, there may be parameters present. - ReflectionUtils.doWithMethods(fbClass, - new ReflectionUtils.MethodCallback() { - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - if (method.getName().equals(factoryMethodName) && - FactoryBean.class.isAssignableFrom(method.getReturnType())) { - objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class); + if (factoryBeanName != null) { + if (factoryMethodName != null) { + // Try to obtain the FactoryBean's object type without instantiating it at all. + BeanDefinition fbDef = getBeanDefinition(factoryBeanName); + if (fbDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) fbDef).hasBeanClass()) { + // CGLIB subclass methods hide generic parameters; look at the original user class. + Class<?> fbClass = ClassUtils.getUserClass(((AbstractBeanDefinition) fbDef).getBeanClass()); + // Find the given factory method, taking into account that in the case of + // @Bean methods, there may be parameters present. + ReflectionUtils.doWithMethods(fbClass, + new ReflectionUtils.MethodCallback() { + @Override + public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { + if (method.getName().equals(factoryMethodName) && + FactoryBean.class.isAssignableFrom(method.getReturnType())) { + objectType.value = GenericTypeResolver.resolveReturnTypeArgument(method, FactoryBean.class); + } } - } - }); - if (objectType.value != null) { - return objectType.value; + }); + if (objectType.value != null) { + return objectType.value; + } } } + // If not resolvable above and the referenced factory bean doesn't exist yet, + // exit here - we don't want to force the creation of another bean just to + // obtain a FactoryBean's object type... + if (!isBeanEligibleForMetadataCaching(factoryBeanName)) { + return null; + } } FactoryBean<?> fb = (mbd.isSingleton() ? @@ -1023,6 +1060,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac final BeanFactory parent = this; if (System.getSecurityManager() != null) { beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { return getInstantiationStrategy().instantiate(mbd, beanName, parent); } @@ -1492,6 +1530,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { invokeAwareMethods(beanName, bean); return null; @@ -1559,6 +1598,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (System.getSecurityManager() != null) { try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + @Override public Object run() throws Exception { ((InitializingBean) bean).afterPropertiesSet(); return null; @@ -1616,6 +1656,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + @Override public Object run() throws Exception { ReflectionUtils.makeAccessible(initMethod); return null; @@ -1623,6 +1664,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac }); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + @Override public Object run() throws Exception { initMethod.invoke(bean); return null; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java index 5094ad71..050c9d1d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinition.java @@ -139,10 +139,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess private String scope = SCOPE_DEFAULT; - private boolean singleton = true; - - private boolean prototype = false; - private boolean abstractFlag = false; private boolean lazyInit = false; @@ -211,17 +207,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * Create a new AbstractBeanDefinition as a deep copy of the given * bean definition. * @param original the original bean definition to copy from - * @deprecated since Spring 2.5, in favor of {@link #AbstractBeanDefinition(BeanDefinition)} - */ - @Deprecated - protected AbstractBeanDefinition(AbstractBeanDefinition original) { - this((BeanDefinition) original); - } - - /** - * Create a new AbstractBeanDefinition as a deep copy of the given - * bean definition. - * @param original the original bean definition to copy from */ protected AbstractBeanDefinition(BeanDefinition original) { setParentName(original.getParentName()); @@ -268,17 +253,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * Override settings in this bean definition (presumably a copied parent * from a parent-child inheritance relationship) from the given bean * definition (presumably the child). - * @deprecated since Spring 2.5, in favor of {@link #overrideFrom(BeanDefinition)} - */ - @Deprecated - public void overrideFrom(AbstractBeanDefinition other) { - overrideFrom((BeanDefinition) other); - } - - /** - * Override settings in this bean definition (presumably a copied parent - * from a parent-child inheritance relationship) from the given bean - * definition (presumably the child). * <ul> * <li>Will override beanClass if specified in the given bean definition. * <li>Will always take {@code abstract}, {@code scope}, @@ -389,10 +363,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess return (Class<?>) beanClassObject; } + @Override public void setBeanClassName(String beanClassName) { this.beanClass = beanClassName; } + @Override public String getBeanClassName() { Object beanClassObject = this.beanClass; if (beanClassObject instanceof Class) { @@ -432,46 +408,27 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * @see #SCOPE_SINGLETON * @see #SCOPE_PROTOTYPE */ + @Override public void setScope(String scope) { this.scope = scope; - this.singleton = SCOPE_SINGLETON.equals(scope) || SCOPE_DEFAULT.equals(scope); - this.prototype = SCOPE_PROTOTYPE.equals(scope); } /** * Return the name of the target scope for the bean. */ + @Override public String getScope() { return this.scope; } /** - * Set if this a <b>Singleton</b>, with a single, shared instance returned - * on all calls. In case of "false", the BeanFactory will apply the <b>Prototype</b> - * design pattern, with each caller requesting an instance getting an independent - * instance. How this is exactly defined will depend on the BeanFactory. - * <p>"Singletons" are the commoner type, so the default is "true". - * Note that as of Spring 2.0, this flag is just an alternative way to - * specify scope="singleton" or scope="prototype". - * @deprecated since Spring 2.5, in favor of {@link #setScope} - * @see #setScope - * @see #SCOPE_SINGLETON - * @see #SCOPE_PROTOTYPE - */ - @Deprecated - public void setSingleton(boolean singleton) { - this.scope = (singleton ? SCOPE_SINGLETON : SCOPE_PROTOTYPE); - this.singleton = singleton; - this.prototype = !singleton; - } - - /** * Return whether this a <b>Singleton</b>, with a single shared instance * returned from all calls. * @see #SCOPE_SINGLETON */ + @Override public boolean isSingleton() { - return this.singleton; + return SCOPE_SINGLETON.equals(scope) || SCOPE_DEFAULT.equals(scope); } /** @@ -479,8 +436,9 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * returned for each call. * @see #SCOPE_PROTOTYPE */ + @Override public boolean isPrototype() { - return this.prototype; + return SCOPE_PROTOTYPE.equals(scope); } /** @@ -497,6 +455,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * Return whether this bean is "abstract", i.e. not meant to be instantiated * itself but rather just serving as parent for concrete child bean definitions. */ + @Override public boolean isAbstract() { return this.abstractFlag; } @@ -506,6 +465,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * <p>If {@code false}, the bean will get instantiated on startup by bean * factories that perform eager initialization of singletons. */ + @Override public void setLazyInit(boolean lazyInit) { this.lazyInit = lazyInit; } @@ -514,6 +474,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * Return whether this bean should be lazily initialized, i.e. not * eagerly instantiated on startup. Only applicable to a singleton bean. */ + @Override public boolean isLazyInit() { return this.lazyInit; } @@ -594,6 +555,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * constructor arguments. This property should just be necessary for other kinds * of dependencies like statics (*ugh*) or database preparation on startup. */ + @Override public void setDependsOn(String[] dependsOn) { this.dependsOn = dependsOn; } @@ -601,6 +563,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Return the bean names that this bean depends on. */ + @Override public String[] getDependsOn() { return this.dependsOn; } @@ -608,6 +571,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Set whether this bean is a candidate for getting autowired into some other bean. */ + @Override public void setAutowireCandidate(boolean autowireCandidate) { this.autowireCandidate = autowireCandidate; } @@ -615,6 +579,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Return whether this bean is a candidate for getting autowired into some other bean. */ + @Override public boolean isAutowireCandidate() { return this.autowireCandidate; } @@ -624,6 +589,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * If this value is true for exactly one bean among multiple * matching candidates, it will serve as a tie-breaker. */ + @Override public void setPrimary(boolean primary) { this.primary = primary; } @@ -633,6 +599,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess * If this value is true for exactly one bean among multiple * matching candidates, it will serve as a tie-breaker. */ + @Override public boolean isPrimary() { return this.primary; } @@ -728,6 +695,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Return constructor argument values for this bean (never {@code null}). */ + @Override public ConstructorArgumentValues getConstructorArgumentValues() { return this.constructorArgumentValues; } @@ -749,6 +717,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Return property values for this bean (never {@code null}). */ + @Override public MutablePropertyValues getPropertyValues() { return this.propertyValues; } @@ -770,18 +739,22 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess } + @Override public void setFactoryBeanName(String factoryBeanName) { this.factoryBeanName = factoryBeanName; } + @Override public String getFactoryBeanName() { return this.factoryBeanName; } + @Override public void setFactoryMethodName(String factoryMethodName) { this.factoryMethodName = factoryMethodName; } + @Override public String getFactoryMethodName() { return this.factoryMethodName; } @@ -878,6 +851,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess /** * Return the role hint for this {@code BeanDefinition}. */ + @Override public int getRole() { return this.role; } @@ -890,6 +864,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess this.description = description; } + @Override public String getDescription() { return this.description; } @@ -917,6 +892,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess this.resource = new DescriptiveResource(resourceDescription); } + @Override public String getResourceDescription() { return (this.resource != null ? this.resource.getDescription() : null); } @@ -928,6 +904,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess this.resource = new BeanDefinitionResource(originatingBd); } + @Override public BeanDefinition getOriginatingBeanDefinition() { return (this.resource instanceof BeanDefinitionResource ? ((BeanDefinitionResource) this.resource).getBeanDefinition() : null); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java index 32db844c..9a267cce 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanDefinitionReader.java @@ -102,6 +102,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable return this.registry; } + @Override public final BeanDefinitionRegistry getRegistry() { return this.registry; } @@ -121,6 +122,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable this.resourceLoader = resourceLoader; } + @Override public ResourceLoader getResourceLoader() { return this.resourceLoader; } @@ -136,6 +138,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable this.beanClassLoader = beanClassLoader; } + @Override public ClassLoader getBeanClassLoader() { return this.beanClassLoader; } @@ -149,6 +152,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable this.environment = environment; } + @Override public Environment getEnvironment() { return this.environment; } @@ -162,11 +166,13 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new DefaultBeanNameGenerator()); } + @Override public BeanNameGenerator getBeanNameGenerator() { return this.beanNameGenerator; } + @Override public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { Assert.notNull(resources, "Resource array must not be null"); int counter = 0; @@ -176,6 +182,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable return counter; } + @Override public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException { return loadBeanDefinitions(location, null); } @@ -236,6 +243,7 @@ public abstract class AbstractBeanDefinitionReader implements EnvironmentCapable } } + @Override public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException { Assert.notNull(locations, "Location array must not be null"); int counter = 0; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java index 77926309..d0a8f18a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java @@ -24,6 +24,7 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; @@ -160,7 +161,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp new ConcurrentHashMap<String, RootBeanDefinition>(64); /** Names of beans that have already been created at least once */ - private final Map<String, Boolean> alreadyCreated = new ConcurrentHashMap<String, Boolean>(64); + private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64)); /** Names of beans that are currently in creation */ private final ThreadLocal<Object> prototypesCurrentlyInCreation = @@ -187,14 +188,17 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp // Implementation of BeanFactory interface //--------------------------------------------------------------------- + @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } + @Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } + @Override public Object getBean(String name, Object... args) throws BeansException { return doGetBean(name, null, args, false); } @@ -280,14 +284,19 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { - getBean(dependsOnBean); + if (isDependent(beanName, dependsOnBean)) { + throw new BeanCreationException(mbd.getResourceDescription(), beanName, + "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'"); + } registerDependentBean(dependsOnBean, beanName); + getBean(dependsOnBean); } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { + @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); @@ -325,6 +334,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { + @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { @@ -367,6 +377,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return (T) bean; } + @Override public boolean containsBean(String name) { String beanName = transformedBeanName(name); if (containsSingleton(beanName) || containsBeanDefinition(beanName)) { @@ -377,6 +388,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name))); } + @Override public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { String beanName = transformedBeanName(name); @@ -422,6 +434,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } } + @Override public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { String beanName = transformedBeanName(name); @@ -446,6 +459,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp final FactoryBean<?> factoryBean = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName); if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + @Override public Boolean run() { return ((factoryBean instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factoryBean).isPrototype()) || !factoryBean.isSingleton()); @@ -463,6 +477,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } } + @Override public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException { String beanName = transformedBeanName(name); Class<?> typeToMatch = (targetType != null ? targetType : Object.class); @@ -543,6 +558,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } } + @Override public Class<?> getType(String name) throws NoSuchBeanDefinitionException { String beanName = transformedBeanName(name); @@ -633,10 +649,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp // Implementation of HierarchicalBeanFactory interface //--------------------------------------------------------------------- + @Override public BeanFactory getParentBeanFactory() { return this.parentBeanFactory; } + @Override public boolean containsLocalBean(String name) { String beanName = transformedBeanName(name); return ((containsSingleton(beanName) || containsBeanDefinition(beanName)) && @@ -648,6 +666,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp // Implementation of ConfigurableBeanFactory interface //--------------------------------------------------------------------- + @Override public void setParentBeanFactory(BeanFactory parentBeanFactory) { if (this.parentBeanFactory != null && this.parentBeanFactory != parentBeanFactory) { throw new IllegalStateException("Already associated with parent BeanFactory: " + this.parentBeanFactory); @@ -655,46 +674,57 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp this.parentBeanFactory = parentBeanFactory; } + @Override public void setBeanClassLoader(ClassLoader beanClassLoader) { this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader()); } + @Override public ClassLoader getBeanClassLoader() { return this.beanClassLoader; } + @Override public void setTempClassLoader(ClassLoader tempClassLoader) { this.tempClassLoader = tempClassLoader; } + @Override public ClassLoader getTempClassLoader() { return this.tempClassLoader; } + @Override public void setCacheBeanMetadata(boolean cacheBeanMetadata) { this.cacheBeanMetadata = cacheBeanMetadata; } + @Override public boolean isCacheBeanMetadata() { return this.cacheBeanMetadata; } + @Override public void setBeanExpressionResolver(BeanExpressionResolver resolver) { this.beanExpressionResolver = resolver; } + @Override public BeanExpressionResolver getBeanExpressionResolver() { return this.beanExpressionResolver; } + @Override public void setConversionService(ConversionService conversionService) { this.conversionService = conversionService; } + @Override public ConversionService getConversionService() { return this.conversionService; } + @Override public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) { Assert.notNull(registrar, "PropertyEditorRegistrar must not be null"); this.propertyEditorRegistrars.add(registrar); @@ -707,12 +737,14 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.propertyEditorRegistrars; } + @Override public void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass) { Assert.notNull(requiredType, "Required type must not be null"); Assert.isAssignable(PropertyEditor.class, propertyEditorClass); this.customEditors.put(requiredType, propertyEditorClass); } + @Override public void copyRegisteredEditorsTo(PropertyEditorRegistry registry) { registerCustomEditors(registry); } @@ -724,6 +756,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.customEditors; } + @Override public void setTypeConverter(TypeConverter typeConverter) { this.typeConverter = typeConverter; } @@ -736,6 +769,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.typeConverter; } + @Override public TypeConverter getTypeConverter() { TypeConverter customConverter = getCustomTypeConverter(); if (customConverter != null) { @@ -750,11 +784,13 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } } + @Override public void addEmbeddedValueResolver(StringValueResolver valueResolver) { Assert.notNull(valueResolver, "StringValueResolver must not be null"); this.embeddedValueResolvers.add(valueResolver); } + @Override public String resolveEmbeddedValue(String value) { String result = value; for (StringValueResolver resolver : this.embeddedValueResolvers) { @@ -766,6 +802,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return result; } + @Override public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null"); this.beanPostProcessors.remove(beanPostProcessor); @@ -778,6 +815,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } } + @Override public int getBeanPostProcessorCount() { return this.beanPostProcessors.size(); } @@ -810,6 +848,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return this.hasDestructionAwareBeanPostProcessors; } + @Override public void registerScope(String scopeName, Scope scope) { Assert.notNull(scopeName, "Scope identifier must not be null"); Assert.notNull(scope, "Scope must not be null"); @@ -819,10 +858,12 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp this.scopes.put(scopeName, scope); } + @Override public String[] getRegisteredScopeNames() { return StringUtils.toStringArray(this.scopes.keySet()); } + @Override public Scope getRegisteredScope(String scopeName) { Assert.notNull(scopeName, "Scope identifier must not be null"); return this.scopes.get(scopeName); @@ -848,6 +889,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp AccessController.getContext()); } + @Override public void copyConfigurationFrom(ConfigurableBeanFactory otherFactory) { Assert.notNull(otherFactory, "BeanFactory must not be null"); setBeanClassLoader(otherFactory.getBeanClassLoader()); @@ -881,6 +923,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * @throws NoSuchBeanDefinitionException if there is no bean with the given name * @throws BeanDefinitionStoreException in case of an invalid bean definition */ + @Override public BeanDefinition getMergedBeanDefinition(String name) throws BeansException { String beanName = transformedBeanName(name); @@ -892,6 +935,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp return getMergedLocalBeanDefinition(beanName); } + @Override public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException { String beanName = transformedBeanName(name); @@ -915,7 +959,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp @Override public boolean isActuallyInCreation(String beanName) { - return isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName); + return (isSingletonCurrentlyInCreation(beanName) || isPrototypeCurrentlyInCreation(beanName)); } /** @@ -974,6 +1018,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } } + @Override public void destroyBean(String beanName, Object beanInstance) { destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName)); } @@ -989,6 +1034,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp new DisposableBeanAdapter(beanInstance, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy(); } + @Override public void destroyScopedBean(String beanName) { RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); if (mbd.isSingleton() || mbd.isPrototype()) { @@ -1261,6 +1307,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp } if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() { + @Override public Class<?> run() throws Exception { return doResolveBeanClass(mbd, typesToMatch); } @@ -1388,8 +1435,8 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * @param beanName the name of the bean */ protected void markBeanAsCreated(String beanName) { - if (!this.alreadyCreated.containsKey(beanName)) { - this.alreadyCreated.put(beanName, Boolean.TRUE); + if (!this.alreadyCreated.contains(beanName)) { + this.alreadyCreated.add(beanName); } } @@ -1409,7 +1456,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * at this point already */ protected boolean isBeanEligibleForMetadataCaching(String beanName) { - return this.alreadyCreated.containsKey(beanName); + return this.alreadyCreated.contains(beanName); } /** @@ -1419,7 +1466,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * @return {@code true} if actually removed, {@code false} otherwise */ protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) { - if (!this.alreadyCreated.containsKey(beanName)) { + if (!this.alreadyCreated.contains(beanName)) { removeSingleton(beanName); return true; } @@ -1580,8 +1627,7 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp * instantiation within this class is performed by this method. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean - * @param args arguments to use if creating a prototype using explicit arguments to a - * static factory method. This parameter must be {@code null} except in this case. + * @param args arguments to use if creating a prototype using explicit arguments * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created */ diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateQualifier.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateQualifier.java index 6846390e..f5991ac9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateQualifier.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateQualifier.java @@ -42,7 +42,7 @@ public class AutowireCandidateQualifier extends BeanMetadataAttributeAccessor { * given type. * @param type the annotation type */ - public AutowireCandidateQualifier(Class type) { + public AutowireCandidateQualifier(Class<?> type) { this(type.getName()); } @@ -65,7 +65,7 @@ public class AutowireCandidateQualifier extends BeanMetadataAttributeAccessor { * @param type the annotation type * @param value the annotation value to match */ - public AutowireCandidateQualifier(Class type, Object value) { + public AutowireCandidateQualifier(Class<?> type, Object value) { this(type.getName(), value); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java index cd2c41e1..2c3e15fc 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireCandidateResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,8 @@ import org.springframework.beans.factory.config.DependencyDescriptor; * Strategy interface for determining whether a specific bean definition * qualifies as an autowire candidate for a specific dependency. * - * @author Mark Fisher * @author Juergen Hoeller + * @author Mark Fisher * @since 2.5 */ public interface AutowireCandidateResolver { @@ -47,4 +47,15 @@ public interface AutowireCandidateResolver { */ Object getSuggestedValue(DependencyDescriptor descriptor); + /** + * Build a proxy for lazy resolution of the actual dependency target, + * if demanded by the injection point. + * @param descriptor the descriptor for the target method parameter or field + * @param beanName the name of the bean that contains the injection point + * @return the lazy resolution proxy for the actual dependency target, + * or {@code null} if straight resolution is to be performed + * @since 4.0 + */ + Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName); + } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java index 1ef3ceaf..5111599f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AutowireUtils.java @@ -58,6 +58,7 @@ abstract class AutowireUtils { */ public static void sortConstructors(Constructor<?>[] constructors) { Arrays.sort(constructors, new Comparator<Constructor<?>>() { + @Override public int compare(Constructor<?> c1, Constructor<?> c2) { boolean p1 = Modifier.isPublic(c1.getModifiers()); boolean p2 = Modifier.isPublic(c2.getModifiers()); @@ -80,6 +81,7 @@ abstract class AutowireUtils { */ public static void sortFactoryMethods(Method[] factoryMethods) { Arrays.sort(factoryMethods, new Comparator<Method>() { + @Override public int compare(Method fm1, Method fm2) { boolean p1 = Modifier.isPublic(fm1.getModifiers()); boolean p2 = Modifier.isPublic(fm2.getModifiers()); @@ -287,6 +289,7 @@ abstract class AutowireUtils { this.objectFactory = objectFactory; } + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String methodName = method.getName(); if (methodName.equals("equals")) { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java index 5b9b571f..f70e163c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,7 @@ public class BeanDefinitionBuilder { * Create a new {@code BeanDefinitionBuilder} used to construct a {@link GenericBeanDefinition}. * @param beanClass the {@code Class} of the bean that the definition is being created for */ - public static BeanDefinitionBuilder genericBeanDefinition(Class beanClass) { + public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) { BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); builder.beanDefinition = new GenericBeanDefinition(); builder.beanDefinition.setBeanClass(beanClass); @@ -67,7 +67,7 @@ public class BeanDefinitionBuilder { * Create a new {@code BeanDefinitionBuilder} used to construct a {@link RootBeanDefinition}. * @param beanClass the {@code Class} of the bean that the definition is being created for */ - public static BeanDefinitionBuilder rootBeanDefinition(Class beanClass) { + public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass) { return rootBeanDefinition(beanClass, null); } @@ -76,7 +76,7 @@ public class BeanDefinitionBuilder { * @param beanClass the {@code Class} of the bean that the definition is being created for * @param factoryMethodName the name of the method to use to construct the bean instance */ - public static BeanDefinitionBuilder rootBeanDefinition(Class beanClass, String factoryMethodName) { + public static BeanDefinitionBuilder rootBeanDefinition(Class<?> beanClass, String factoryMethodName) { BeanDefinitionBuilder builder = new BeanDefinitionBuilder(); builder.beanDefinition = new RootBeanDefinition(); builder.beanDefinition.setBeanClass(beanClass); @@ -167,18 +167,6 @@ public class BeanDefinitionBuilder { } /** - * Set the name of the factory bean to use for this definition. - * @deprecated since Spring 2.5, in favor of preparing this on the - * {@link #getRawBeanDefinition() raw BeanDefinition object} - */ - @Deprecated - public BeanDefinitionBuilder setFactoryBean(String factoryBean, String factoryMethod) { - this.beanDefinition.setFactoryBeanName(factoryBean); - this.beanDefinition.setFactoryMethodName(factoryMethod); - return this; - } - - /** * Add an indexed constructor arg value. The current index is tracked internally * and all additions are at the present point. * @deprecated since Spring 2.5, in favor of {@link #addConstructorArgValue} @@ -254,17 +242,6 @@ public class BeanDefinitionBuilder { } /** - * Set whether or not this definition describes a singleton bean, - * as alternative to {@link #setScope}. - * @deprecated since Spring 2.5, in favor of {@link #setScope} - */ - @Deprecated - public BeanDefinitionBuilder setSingleton(boolean singleton) { - this.beanDefinition.setSingleton(singleton); - return this; - } - - /** * Set whether or not this definition is abstract. */ public BeanDefinitionBuilder setAbstract(boolean flag) { @@ -319,26 +296,4 @@ public class BeanDefinitionBuilder { return this; } - /** - * Set the source of this definition. - * @deprecated since Spring 2.5, in favor of preparing this on the - * {@link #getRawBeanDefinition() raw BeanDefinition object} - */ - @Deprecated - public BeanDefinitionBuilder setSource(Object source) { - this.beanDefinition.setSource(source); - return this; - } - - /** - * Set the description associated with this definition. - * @deprecated since Spring 2.5, in favor of preparing this on the - * {@link #getRawBeanDefinition() raw BeanDefinition object} - */ - @Deprecated - public BeanDefinitionBuilder setResourceDescription(String resourceDescription) { - this.beanDefinition.setResourceDescription(resourceDescription); - return this; - } - } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionResource.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionResource.java index 330b6990..7de75a1b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionResource.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionResource.java @@ -64,11 +64,13 @@ class BeanDefinitionResource extends AbstractResource { return false; } + @Override public InputStream getInputStream() throws IOException { throw new FileNotFoundException( "Resource cannot be opened because it points to " + getDescription()); } + @Override public String getDescription() { return "BeanDefinition defined in " + this.beanDefinition.getResourceDescription(); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java index 076e2098..82265bfd 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/CglibSubclassingInstantiationStrategy.java @@ -22,11 +22,14 @@ import java.lang.reflect.Method; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.BeanInstantiationException; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.cglib.core.SpringNamingPolicy; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.CallbackFilter; import org.springframework.cglib.proxy.Enhancer; +import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import org.springframework.cglib.proxy.NoOp; @@ -39,6 +42,7 @@ import org.springframework.cglib.proxy.NoOp; * * @author Rod Johnson * @author Juergen Hoeller + * @author Sam Brannen * @since 1.1 */ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy { @@ -63,18 +67,17 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt @Override - protected Object instantiateWithMethodInjection( - RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { + protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition, String beanName, + BeanFactory owner) { - // Must generate CGLIB subclass. - return new CglibSubclassCreator(beanDefinition, owner).instantiate(null, null); + return instantiateWithMethodInjection(beanDefinition, beanName, owner, null, null); } @Override - protected Object instantiateWithMethodInjection( - RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, - Constructor<?> ctor, Object[] args) { + protected Object instantiateWithMethodInjection(RootBeanDefinition beanDefinition, String beanName, + BeanFactory owner, Constructor<?> ctor, Object[] args) { + // Must generate CGLIB subclass. return new CglibSubclassCreator(beanDefinition, owner).instantiate(ctor, args); } @@ -85,13 +88,14 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt */ private static class CglibSubclassCreator { - private static final Log logger = LogFactory.getLog(CglibSubclassCreator.class); + private static final Class<?>[] CALLBACK_TYPES = new Class<?>[] + {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class}; private final RootBeanDefinition beanDefinition; private final BeanFactory owner; - public CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) { + CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) { this.beanDefinition = beanDefinition; this.owner = owner; } @@ -105,99 +109,148 @@ public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationSt * Ignored if the {@code ctor} parameter is {@code null}. * @return new instance of the dynamically generated subclass */ - public Object instantiate(Constructor<?> ctor, Object[] args) { + Object instantiate(Constructor<?> ctor, Object[] args) { + Class<?> subclass = createEnhancedSubclass(this.beanDefinition); + Object instance; + if (ctor == null) { + instance = BeanUtils.instantiate(subclass); + } + else { + try { + Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes()); + instance = enhancedSubclassConstructor.newInstance(args); + } + catch (Exception ex) { + throw new BeanInstantiationException(this.beanDefinition.getBeanClass(), String.format( + "Failed to invoke constructor for CGLIB enhanced subclass [%s]", subclass.getName()), ex); + } + } + // SPR-10785: set callbacks directly on the instance instead of in the + // enhanced class (via the Enhancer) in order to avoid memory leaks. + Factory factory = (Factory) instance; + factory.setCallbacks(new Callback[] {NoOp.INSTANCE, + new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner), + new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)}); + return instance; + } + + /** + * Create an enhanced subclass of the bean class for the provided bean + * definition, using CGLIB. + */ + private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) { Enhancer enhancer = new Enhancer(); - enhancer.setSuperclass(this.beanDefinition.getBeanClass()); + enhancer.setSuperclass(beanDefinition.getBeanClass()); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); - enhancer.setCallbackFilter(new CallbackFilterImpl()); - enhancer.setCallbacks(new Callback[] { - NoOp.INSTANCE, - new LookupOverrideMethodInterceptor(), - new ReplaceOverrideMethodInterceptor() - }); - - return (ctor != null ? enhancer.create(ctor.getParameterTypes(), args) : enhancer.create()); + enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition)); + enhancer.setCallbackTypes(CALLBACK_TYPES); + return enhancer.createClass(); } + } - /** - * Class providing hashCode and equals methods required by CGLIB to - * ensure that CGLIB doesn't generate a distinct class per bean. - * Identity is based on class and bean definition. - */ - private class CglibIdentitySupport { + /** + * Class providing hashCode and equals methods required by CGLIB to + * ensure that CGLIB doesn't generate a distinct class per bean. + * Identity is based on class and bean definition. + */ + private static class CglibIdentitySupport { - /** - * Exposed for equals method to allow access to enclosing class field - */ - protected RootBeanDefinition getBeanDefinition() { - return beanDefinition; - } + private final RootBeanDefinition beanDefinition; - @Override - public boolean equals(Object other) { - return (other.getClass().equals(getClass()) && - ((CglibIdentitySupport) other).getBeanDefinition().equals(beanDefinition)); - } + CglibIdentitySupport(RootBeanDefinition beanDefinition) { + this.beanDefinition = beanDefinition; + } - @Override - public int hashCode() { - return beanDefinition.hashCode(); - } + RootBeanDefinition getBeanDefinition() { + return this.beanDefinition; } + @Override + public boolean equals(Object other) { + return (getClass().equals(other.getClass()) && + this.beanDefinition.equals(((CglibIdentitySupport) other).beanDefinition)); + } - /** - * CGLIB MethodInterceptor to override methods, replacing them with an - * implementation that returns a bean looked up in the container. - */ - private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { + @Override + public int hashCode() { + return this.beanDefinition.hashCode(); + } + } + + + /** + * CGLIB callback for filtering method interception behavior. + */ + private static class MethodOverrideCallbackFilter extends CglibIdentitySupport implements CallbackFilter { + + private static final Log logger = LogFactory.getLog(MethodOverrideCallbackFilter.class); - public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { - // Cast is safe, as CallbackFilter filters are used selectively. - LookupOverride lo = (LookupOverride) beanDefinition.getMethodOverrides().getOverride(method); - return owner.getBean(lo.getBeanName()); + MethodOverrideCallbackFilter(RootBeanDefinition beanDefinition) { + super(beanDefinition); + } + + @Override + public int accept(Method method) { + MethodOverride methodOverride = getBeanDefinition().getMethodOverrides().getOverride(method); + if (logger.isTraceEnabled()) { + logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]"); + } + if (methodOverride == null) { + return PASSTHROUGH; + } + else if (methodOverride instanceof LookupOverride) { + return LOOKUP_OVERRIDE; } + else if (methodOverride instanceof ReplaceOverride) { + return METHOD_REPLACER; + } + throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " + + methodOverride.getClass().getName()); } + } - /** - * CGLIB MethodInterceptor to override methods, replacing them with a call - * to a generic MethodReplacer. - */ - private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { + /** + * CGLIB MethodInterceptor to override methods, replacing them with an + * implementation that returns a bean looked up in the container. + */ + private static class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { - public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { - ReplaceOverride ro = (ReplaceOverride) beanDefinition.getMethodOverrides().getOverride(method); - // TODO could cache if a singleton for minor performance optimization - MethodReplacer mr = (MethodReplacer) owner.getBean(ro.getMethodReplacerBeanName()); - return mr.reimplement(obj, method, args); - } + private final BeanFactory owner; + + LookupOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) { + super(beanDefinition); + this.owner = owner; + } + + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { + // Cast is safe, as CallbackFilter filters are used selectively. + LookupOverride lo = (LookupOverride) getBeanDefinition().getMethodOverrides().getOverride(method); + return this.owner.getBean(lo.getBeanName()); } + } + /** + * CGLIB MethodInterceptor to override methods, replacing them with a call + * to a generic MethodReplacer. + */ + private static class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor { - /** - * CGLIB object to filter method interception behavior. - */ - private class CallbackFilterImpl extends CglibIdentitySupport implements CallbackFilter { + private final BeanFactory owner; - public int accept(Method method) { - MethodOverride methodOverride = beanDefinition.getMethodOverrides().getOverride(method); - if (logger.isTraceEnabled()) { - logger.trace("Override for '" + method.getName() + "' is [" + methodOverride + "]"); - } - if (methodOverride == null) { - return PASSTHROUGH; - } - else if (methodOverride instanceof LookupOverride) { - return LOOKUP_OVERRIDE; - } - else if (methodOverride instanceof ReplaceOverride) { - return METHOD_REPLACER; - } - throw new UnsupportedOperationException( - "Unexpected MethodOverride subclass: " + methodOverride.getClass().getName()); - } + ReplaceOverrideMethodInterceptor(RootBeanDefinition beanDefinition, BeanFactory owner) { + super(beanDefinition); + this.owner = owner; + } + + @Override + public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable { + ReplaceOverride ro = (ReplaceOverride) getBeanDefinition().getMethodOverrides().getOverride(method); + // TODO could cache if a singleton for minor performance optimization + MethodReplacer mr = this.owner.getBean(ro.getMethodReplacerBeanName(), MethodReplacer.class); + return mr.reimplement(obj, method, args); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java index 72ab68bd..87fc66ba 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ChildBeanDefinition.java @@ -17,7 +17,6 @@ package org.springframework.beans.factory.support; import org.springframework.beans.MutablePropertyValues; -import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.util.ObjectUtils; @@ -128,14 +127,16 @@ public class ChildBeanDefinition extends AbstractBeanDefinition { * @param original the original bean definition to copy from */ public ChildBeanDefinition(ChildBeanDefinition original) { - super((BeanDefinition) original); + super(original); } + @Override public void setParentName(String parentName) { this.parentName = parentName; } + @Override public String getParentName() { return this.parentName; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java index 7cb8fd18..d148d444 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java @@ -68,11 +68,6 @@ import org.springframework.util.StringUtils; */ class ConstructorResolver { - private static final String CONSTRUCTOR_PROPERTIES_CLASS_NAME = "java.beans.ConstructorProperties"; - - private static final boolean constructorPropertiesAnnotationAvailable = - ClassUtils.isPresent(CONSTRUCTOR_PROPERTIES_CLASS_NAME, ConstructorResolver.class.getClassLoader()); - private final AbstractAutowireCapableBeanFactory beanFactory; @@ -180,10 +175,7 @@ class ConstructorResolver { ArgumentsHolder argsHolder; if (resolvedValues != null) { try { - String[] paramNames = null; - if (constructorPropertiesAnnotationAvailable) { - paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); - } + String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length); if (paramNames == null) { ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer(); if (pnd != null) { @@ -267,6 +259,7 @@ class ConstructorResolver { final Constructor<?> ctorToUse = constructorToUse; final Object[] argumentsToUse = argsToUse; beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { return beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, beanFactory, ctorToUse, argumentsToUse); @@ -582,6 +575,7 @@ class ConstructorResolver { final Method factoryMethod = factoryMethodToUse; final Object[] args = argsToUse; beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { return beanFactory.getInstantiationStrategy().instantiate( mbd, beanName, beanFactory, fb, factoryMethod, args); @@ -891,7 +885,7 @@ class ConstructorResolver { /** - * Inner class to avoid a Java 6 dependency. + * Delegate for checking Java 6's {@link ConstructorProperties} annotation. */ private static class ConstructorPropertiesChecker { diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultBeanNameGenerator.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultBeanNameGenerator.java index 065c4e21..ebd7a702 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultBeanNameGenerator.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultBeanNameGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ import org.springframework.beans.factory.config.BeanDefinition; */ public class DefaultBeanNameGenerator implements BeanNameGenerator { + @Override public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) { return BeanDefinitionReaderUtils.generateBeanName(definition, registry); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 3823dd70..9e422fcc 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -29,6 +29,8 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -126,6 +128,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto /** Whether to allow eager class loading even for lazy-init beans */ private boolean allowEagerClassLoading = true; + /** Optional OrderComparator for dependency Lists and arrays */ + private Comparator<Object> dependencyComparator; + /** Resolver to use for checking if a bean definition is an autowire candidate */ private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver(); @@ -207,6 +212,22 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } /** + * Set a {@link java.util.Comparator} for dependency Lists and arrays. + * @see org.springframework.core.OrderComparator + * @see org.springframework.core.annotation.AnnotationAwareOrderComparator + */ + public void setDependencyComparator(Comparator<Object> dependencyComparator) { + this.dependencyComparator = dependencyComparator; + } + + /** + * Return the dependency comparator for this BeanFactory (may be {@code null}. + */ + public Comparator<Object> getDependencyComparator() { + return this.dependencyComparator; + } + + /** * Set a custom autowire candidate resolver for this BeanFactory to use * when deciding whether a bean definition should be considered as a * candidate for autowiring. @@ -217,6 +238,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto if (System.getSecurityManager() != null) { final BeanFactory target = this; AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { ((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(target); return null; @@ -255,6 +277,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto // Implementation of ListableBeanFactory interface //--------------------------------------------------------------------- + @Override public <T> T getBean(Class<T> requiredType) throws BeansException { Assert.notNull(requiredType, "Required type must not be null"); String[] beanNames = getBeanNamesForType(requiredType); @@ -303,10 +326,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return this.beanDefinitionMap.containsKey(beanName); } + @Override public int getBeanDefinitionCount() { return this.beanDefinitionMap.size(); } + @Override public String[] getBeanDefinitionNames() { synchronized (this.beanDefinitionMap) { if (this.frozenBeanDefinitionNames != null) { @@ -318,10 +343,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } + @Override public String[] getBeanNamesForType(Class<?> type) { return getBeanNamesForType(type, true, true); } + @Override public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { if (!isConfigurationFrozen() || type == null || !allowEagerInit) { return doGetBeanNamesForType(type, includeNonSingletons, allowEagerInit); @@ -427,10 +454,12 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return (factoryBeanName != null && isFactoryBean(factoryBeanName) && !containsSingleton(factoryBeanName)); } + @Override public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException { return getBeansOfType(type, true, true); } + @Override public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException { @@ -461,6 +490,24 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return result; } + @Override + public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) { + List<String> results = new ArrayList<String>(); + for (String beanName : getBeanDefinitionNames()) { + BeanDefinition beanDefinition = getBeanDefinition(beanName); + if (!beanDefinition.isAbstract() && findAnnotationOnBean(beanName, annotationType) != null) { + results.add(beanName); + } + } + for (String beanName : getSingletonNames()) { + if (!results.contains(beanName) && findAnnotationOnBean(beanName, annotationType) != null) { + results.add(beanName); + } + } + return results.toArray(new String[results.size()]); + } + + @Override public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) { Map<String, Object> results = new LinkedHashMap<String, Object>(); for (String beanName : getBeanDefinitionNames()) { @@ -483,6 +530,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto * found on the given class itself, as well as checking its raw bean class * if not found on the exposed bean reference (e.g. in case of a proxy). */ + @Override public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) throws NoSuchBeanDefinitionException{ @@ -508,6 +556,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto // Implementation of ConfigurableListableBeanFactory interface //--------------------------------------------------------------------- + @Override public void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue) { Assert.notNull(dependencyType, "Type must not be null"); if (autowiredValue != null) { @@ -517,24 +566,37 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } + @Override public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor) throws NoSuchBeanDefinitionException { - // Consider FactoryBeans as autowiring candidates. - boolean isFactoryBean = (descriptor != null && descriptor.getDependencyType() != null && - FactoryBean.class.isAssignableFrom(descriptor.getDependencyType())); - if (isFactoryBean) { - beanName = BeanFactoryUtils.transformedBeanName(beanName); - } + return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver()); + } - if (containsBeanDefinition(beanName)) { - return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanName), descriptor); + /** + * Determine whether the specified bean definition qualifies as an autowire candidate, + * to be injected into other beans which declare a dependency of matching type. + * @param beanName the name of the bean definition to check + * @param descriptor the descriptor of the dependency to resolve + * @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm + * @return whether the bean should be considered as autowire candidate + */ + protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver) + throws NoSuchBeanDefinitionException { + + String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName); + if (containsBeanDefinition(beanDefinitionName)) { + return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver); } else if (containsSingleton(beanName)) { - return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor); + return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver); } - else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) { + else if (getParentBeanFactory() instanceof DefaultListableBeanFactory) { // No bean definition found in this factory -> delegate to parent. + return ((DefaultListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor, resolver); + } + else if (getParentBeanFactory() instanceof ConfigurableListableBeanFactory) { + // If no DefaultListableBeanFactory, can't pass the resolver along. return ((ConfigurableListableBeanFactory) getParentBeanFactory()).isAutowireCandidate(beanName, descriptor); } else { @@ -548,10 +610,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto * @param beanName the name of the bean definition to check * @param mbd the merged bean definition to check * @param descriptor the descriptor of the dependency to resolve + * @param resolver the AutowireCandidateResolver to use for the actual resolution algorithm * @return whether the bean should be considered as autowire candidate */ - protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, DependencyDescriptor descriptor) { - resolveBeanClass(mbd, beanName); + protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd, + DependencyDescriptor descriptor, AutowireCandidateResolver resolver) { + + String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName); + resolveBeanClass(mbd, beanDefinitionName); if (mbd.isFactoryMethodUnique) { boolean resolve; synchronized (mbd.constructorArgumentLock) { @@ -561,8 +627,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd); } } - return getAutowireCandidateResolver().isAutowireCandidate( - new BeanDefinitionHolder(mbd, beanName, getAliases(beanName)), descriptor); + return resolver.isAutowireCandidate( + new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor); } @Override @@ -577,6 +643,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return bd; } + @Override public void freezeConfiguration() { this.configurationFrozen = true; synchronized (this.beanDefinitionMap) { @@ -584,6 +651,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } + @Override public boolean isConfigurationFrozen() { return this.configurationFrozen; } @@ -598,9 +666,10 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return (this.configurationFrozen || super.isBeanEligibleForMetadataCaching(beanName)); } + @Override public void preInstantiateSingletons() throws BeansException { - if (this.logger.isInfoEnabled()) { - this.logger.info("Pre-instantiating singletons in " + this); + if (this.logger.isDebugEnabled()) { + this.logger.debug("Pre-instantiating singletons in " + this); } List<String> beanNames; @@ -619,6 +688,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() { + @Override public Boolean run() { return ((SmartFactoryBean<?>) factory).isEagerInit(); } @@ -644,6 +714,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto // Implementation of BeanDefinitionRegistry interface //--------------------------------------------------------------------- + @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { @@ -670,6 +741,14 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } + else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) { + // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE + if (this.logger.isWarnEnabled()) { + this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + + " with a framework-generated bean definition ': replacing [" + + oldBeanDefinition + "] with [" + beanDefinition + "]"); + } + } else { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + @@ -689,6 +768,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } + @Override public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { Assert.hasText(beanName, "'beanName' must not be empty"); @@ -765,6 +845,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto // Dependency resolution functionality //--------------------------------------------------------------------- + @Override public Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { @@ -776,13 +857,18 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName); } else { - return doResolveDependency(descriptor, descriptor.getDependencyType(), beanName, autowiredBeanNames, typeConverter); + Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName); + if (result == null) { + result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter); + } + return result; } } - protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName, + public Object doResolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { + Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { @@ -798,7 +884,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto if (type.isArray()) { Class<?> componentType = type.getComponentType(); - Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor); + DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); + targetDesc.increaseNestingLevel(); + Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor); @@ -809,7 +897,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); - return converter.convertIfNecessary(matchingBeans.values(), type); + Object result = converter.convertIfNecessary(matchingBeans.values(), type); + if (this.dependencyComparator != null && result instanceof Object[]) { + Arrays.sort((Object[]) result, this.dependencyComparator); + } + return result; } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class<?> elementType = descriptor.getCollectionType(); @@ -819,7 +911,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } return null; } - Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor); + DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); + targetDesc.increaseNestingLevel(); + Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor); @@ -830,7 +924,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); - return converter.convertIfNecessary(matchingBeans.values(), type); + Object result = converter.convertIfNecessary(matchingBeans.values(), type); + if (this.dependencyComparator != null && result instanceof List) { + Collections.sort((List<?>) result, this.dependencyComparator); + } + return result; } else if (Map.class.isAssignableFrom(type) && type.isInterface()) { Class<?> keyType = descriptor.getMapKeyType(); @@ -848,7 +946,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } return null; } - Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); + DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); + targetDesc.increaseNestingLevel(); + Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); @@ -917,10 +1017,18 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } for (String candidateName : candidateNames) { - if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, descriptor)) { + if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) { result.put(candidateName, getBean(candidateName)); } } + if (result.isEmpty()) { + DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); + for (String candidateName : candidateNames) { + if (!candidateName.equals(beanName) && isAutowireCandidate(candidateName, fallbackDescriptor)) { + result.put(candidateName, getBean(candidateName)); + } + } + } return result; } @@ -988,6 +1096,17 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } /** + * Determine whether the given beanName/candidateName pair indicates a self reference, + * i.e. whether the candidate points back to the original bean or to a factory method + * on the original bean. + */ + private boolean isSelfReference(String beanName, String candidateName) { + return (beanName != null && candidateName != null && + (beanName.equals(candidateName) || (containsBeanDefinition(candidateName) && + beanName.equals(getMergedLocalBeanDefinition(candidateName).getFactoryBeanName())))); + } + + /** * Raise a NoSuchBeanDefinitionException for an unresolvable dependency. */ private void raiseNoSuchBeanDefinitionException( @@ -1079,8 +1198,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto this.beanName = beanName; } + @Override public Object getObject() throws BeansException { - return doResolveDependency(this.descriptor, this.descriptor.getDependencyType(), this.beanName, null, null); + return doResolveDependency(this.descriptor, this.beanName, null, null); } } @@ -1094,6 +1214,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto super(descriptor, beanName); } + @Override public Object get() throws BeansException { return getObject(); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java index 4ad522a1..987fb797 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,9 @@ package org.springframework.beans.factory.support; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -92,11 +94,13 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements /** Set of registered singletons, containing the bean names in registration order */ private final Set<String> registeredSingletons = new LinkedHashSet<String>(64); - /** Names of beans that are currently in creation (using a ConcurrentHashMap as a Set) */ - private final Map<String, Boolean> singletonsCurrentlyInCreation = new ConcurrentHashMap<String, Boolean>(16); + /** Names of beans that are currently in creation */ + private final Set<String> singletonsCurrentlyInCreation = + Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16)); - /** Names of beans currently excluded from in creation checks (using a ConcurrentHashMap as a Set) */ - private final Map<String, Boolean> inCreationCheckExclusions = new ConcurrentHashMap<String, Boolean>(16); + /** Names of beans currently excluded from in creation checks */ + private final Set<String> inCreationCheckExclusions = + Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16)); /** List of suppressed Exceptions, available for associating related causes */ private Set<Exception> suppressedExceptions; @@ -117,6 +121,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64); + @Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, "'beanName' must not be null"); synchronized (this.singletonObjects) { @@ -152,7 +157,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * @param beanName the name of the bean * @param singletonFactory the factory for the singleton object */ - protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) { + protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { @@ -163,6 +168,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements } } + @Override public Object getSingleton(String beanName) { return getSingleton(beanName, true); } @@ -270,16 +276,19 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements } } + @Override public boolean containsSingleton(String beanName) { - return (this.singletonObjects.containsKey(beanName)); + return this.singletonObjects.containsKey(beanName); } + @Override public String[] getSingletonNames() { synchronized (this.singletonObjects) { return StringUtils.toStringArray(this.registeredSingletons); } } + @Override public int getSingletonCount() { synchronized (this.singletonObjects) { return this.registeredSingletons.size(); @@ -290,7 +299,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements public void setCurrentlyInCreation(String beanName, boolean inCreation) { Assert.notNull(beanName, "Bean name must not be null"); if (!inCreation) { - this.inCreationCheckExclusions.put(beanName, Boolean.TRUE); + this.inCreationCheckExclusions.add(beanName); } else { this.inCreationCheckExclusions.remove(beanName); @@ -299,7 +308,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements public boolean isCurrentlyInCreation(String beanName) { Assert.notNull(beanName, "Bean name must not be null"); - return (!this.inCreationCheckExclusions.containsKey(beanName) && isActuallyInCreation(beanName)); + return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName)); } protected boolean isActuallyInCreation(String beanName) { @@ -312,18 +321,17 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * @param beanName the name of the bean */ public boolean isSingletonCurrentlyInCreation(String beanName) { - return this.singletonsCurrentlyInCreation.containsKey(beanName); + return this.singletonsCurrentlyInCreation.contains(beanName); } /** * Callback before singleton creation. - * <p>Default implementation register the singleton as currently in creation. + * <p>The default implementation register the singleton as currently in creation. * @param beanName the name of the singleton about to be created * @see #isSingletonCurrentlyInCreation */ protected void beforeSingletonCreation(String beanName) { - if (!this.inCreationCheckExclusions.containsKey(beanName) && - this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) { + if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } } @@ -335,8 +343,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * @see #isSingletonCurrentlyInCreation */ protected void afterSingletonCreation(String beanName) { - if (!this.inCreationCheckExclusions.containsKey(beanName) && - !this.singletonsCurrentlyInCreation.remove(beanName)) { + if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } } @@ -405,6 +412,41 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements } /** + * Determine whether the specified dependent bean has been registered as + * dependent on the given bean or on any of its transitive dependencies. + * @param beanName the name of the bean to check + * @param dependentBeanName the name of the dependent bean + * @since 4.0 + */ + protected boolean isDependent(String beanName, String dependentBeanName) { + return isDependent(beanName, dependentBeanName, null); + } + + private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) { + String canonicalName = canonicalName(beanName); + if (alreadySeen != null && alreadySeen.contains(beanName)) { + return false; + } + Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName); + if (dependentBeans == null) { + return false; + } + if (dependentBeans.contains(dependentBeanName)) { + return true; + } + for (String transitiveDependency : dependentBeans) { + if (alreadySeen == null) { + alreadySeen = new HashSet<String>(); + } + alreadySeen.add(beanName); + if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { + return true; + } + } + return false; + } + + /** * Determine whether a dependent bean has been registered for the given name. * @param beanName the name of the bean to check */ @@ -440,8 +482,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements } public void destroySingletons() { - if (logger.isInfoEnabled()) { - logger.info("Destroying singletons in " + this); + if (logger.isDebugEnabled()) { + logger.debug("Destroying singletons in " + this); } synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java index ae394ca7..39721647 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DisposableBeanAdapter.java @@ -141,6 +141,22 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { /** * Create a new DisposableBeanAdapter for the given bean. + * @param bean the bean instance (never {@code null}) + * @param postProcessors the List of BeanPostProcessors + * (potentially DestructionAwareBeanPostProcessor), if any + */ + public DisposableBeanAdapter(Object bean, List<BeanPostProcessor> postProcessors, AccessControlContext acc) { + Assert.notNull(bean, "Disposable bean must not be null"); + this.bean = bean; + this.beanName = null; + this.invokeDisposableBean = (this.bean instanceof DisposableBean); + this.nonPublicAccessAllowed = true; + this.acc = acc; + this.beanPostProcessors = filterPostProcessors(postProcessors); + } + + /** + * Create a new DisposableBeanAdapter for the given bean. */ private DisposableBeanAdapter(Object bean, String beanName, boolean invokeDisposableBean, boolean nonPublicAccessAllowed, String destroyMethodName, @@ -211,10 +227,12 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { } + @Override public void run() { destroy(); } + @Override public void destroy() { if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { @@ -229,6 +247,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + @Override public Object run() throws Exception { ((DisposableBean) bean).destroy(); return null; @@ -266,6 +285,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { try { if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedAction<Method>() { + @Override public Method run() { return findDestroyMethod(); } @@ -306,6 +326,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { ReflectionUtils.makeAccessible(destroyMethod); return null; @@ -313,6 +334,7 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable { }); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + @Override public Object run() throws Exception { destroyMethod.invoke(bean, args); return null; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java index c5239b5a..53dc1765 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/FactoryBeanRegistrySupport.java @@ -56,6 +56,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg try { if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() { + @Override public Class<?> run() { return factoryBean.getObjectType(); } @@ -153,6 +154,7 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg AccessControlContext acc = getAccessControlContext(); try { object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() { + @Override public Object run() throws Exception { return factory.getObject(); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericBeanDefinition.java index b8f0370c..77c08f67 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericBeanDefinition.java @@ -66,10 +66,12 @@ public class GenericBeanDefinition extends AbstractBeanDefinition { } + @Override public void setParentName(String parentName) { this.parentName = parentName; } + @Override public String getParentName() { return this.parentName; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java new file mode 100644 index 00000000..65554ce9 --- /dev/null +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/GenericTypeAwareAutowireCandidateResolver.java @@ -0,0 +1,170 @@ +/* + * Copyright 2002-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.beans.factory.support; + +import java.lang.reflect.Method; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.core.ResolvableType; +import org.springframework.util.ClassUtils; + +/** + * Basic {@link AutowireCandidateResolver} that performs a full generic type + * match with the candidate's type if the dependency is declared as a generic type + * (e.g. Repository<Customer>). + * + * <p>This is the base class for + * {@link org.springframework.beans.factory.annotation.QualifierAnnotationAutowireCandidateResolver}, + * providing an implementation all non-annotation-based resolution steps at this level. + * + * @author Juergen Hoeller + * @since 4.0 + */ +public class GenericTypeAwareAutowireCandidateResolver implements AutowireCandidateResolver, BeanFactoryAware { + + private BeanFactory beanFactory; + + + @Override + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + protected final BeanFactory getBeanFactory() { + return this.beanFactory; + } + + + @Override + public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { + if (!bdHolder.getBeanDefinition().isAutowireCandidate()) { + // if explicitly false, do not proceed with any other checks + return false; + } + return (descriptor == null || checkGenericTypeMatch(bdHolder, descriptor)); + } + + /** + * Match the given dependency type with its generic type information against the given + * candidate bean definition. + */ + protected boolean checkGenericTypeMatch(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { + ResolvableType dependencyType = descriptor.getResolvableType(); + if (dependencyType.getType() instanceof Class) { + // No generic type -> we know it's a Class type-match, so no need to check again. + return true; + } + ResolvableType targetType = null; + RootBeanDefinition rbd = null; + if (bdHolder.getBeanDefinition() instanceof RootBeanDefinition) { + rbd = (RootBeanDefinition) bdHolder.getBeanDefinition(); + } + if (rbd != null) { + // First, check factory method return type, if applicable + targetType = getReturnTypeForFactoryMethod(rbd, descriptor); + if (targetType == null) { + RootBeanDefinition dbd = getResolvedDecoratedDefinition(rbd); + if (dbd != null) { + targetType = getReturnTypeForFactoryMethod(dbd, descriptor); + } + } + } + if (targetType == null) { + // Regular case: straight bean instance, with BeanFactory available. + if (this.beanFactory != null) { + Class<?> beanType = this.beanFactory.getType(bdHolder.getBeanName()); + if (beanType != null) { + targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanType)); + } + } + // Fallback: no BeanFactory set, or no type resolvable through it + // -> best-effort match against the target class if applicable. + if (targetType == null && rbd != null && rbd.hasBeanClass() && rbd.getFactoryMethodName() == null) { + Class<?> beanClass = rbd.getBeanClass(); + if (!FactoryBean.class.isAssignableFrom(beanClass)) { + targetType = ResolvableType.forClass(ClassUtils.getUserClass(beanClass)); + } + } + } + if (targetType == null || (descriptor.fallbackMatchAllowed() && targetType.hasUnresolvableGenerics())) { + return true; + } + // Full check for complex generic type match... + return dependencyType.isAssignableFrom(targetType); + } + + protected RootBeanDefinition getResolvedDecoratedDefinition(RootBeanDefinition rbd) { + BeanDefinitionHolder decDef = rbd.getDecoratedDefinition(); + if (decDef != null && this.beanFactory instanceof ConfigurableListableBeanFactory) { + ConfigurableListableBeanFactory clbf = (ConfigurableListableBeanFactory) this.beanFactory; + if (clbf.containsBeanDefinition(decDef.getBeanName())) { + BeanDefinition dbd = clbf.getMergedBeanDefinition(decDef.getBeanName()); + if (dbd instanceof RootBeanDefinition) { + return (RootBeanDefinition) dbd; + } + } + } + return null; + } + + protected ResolvableType getReturnTypeForFactoryMethod(RootBeanDefinition rbd, DependencyDescriptor descriptor) { + // Should typically be set for any kind of factory method, since the BeanFactory + // pre-resolves them before reaching out to the AutowireCandidateResolver... + Class<?> preResolved = rbd.resolvedFactoryMethodReturnType; + if (preResolved != null) { + return ResolvableType.forClass(preResolved); + } + else { + Method resolvedFactoryMethod = rbd.getResolvedFactoryMethod(); + if (resolvedFactoryMethod != null) { + if (descriptor.getDependencyType().isAssignableFrom(resolvedFactoryMethod.getReturnType())) { + // Only use factory method metadata if the return type is actually expressive enough + // for our dependency. Otherwise, the returned instance type may have matched instead + // in case of a singleton instance having been registered with the container already. + return ResolvableType.forMethodReturnType(resolvedFactoryMethod); + } + } + return null; + } + } + + + /** + * This implementation always returns {@code null}, leaving suggested value support up + * to subclasses. + */ + @Override + public Object getSuggestedValue(DependencyDescriptor descriptor) { + return null; + } + + /** + * This implementation always returns {@code null}, leaving lazy resolution support up + * to subclasses. + */ + @Override + public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName) { + return null; + } + +} diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java index 6aa560ce..4d4f62f7 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/LookupOverride.java @@ -77,7 +77,7 @@ public class LookupOverride extends MethodOverride { @Override public String toString() { - return "LookupOverride for method '" + getMethodName() + "'; will return bean '" + this.beanName + "'"; + return "LookupOverride for method '" + getMethodName() + "'"; } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedArray.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedArray.java index e7e7ec7d..e47d5dbe 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedArray.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedArray.java @@ -29,7 +29,7 @@ import org.springframework.util.Assert; public class ManagedArray extends ManagedList<Object> { /** Resolved element type for runtime creation of the target array */ - volatile Class resolvedElementType; + volatile Class<?> resolvedElementType; /** diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedList.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedList.java index 5c9aa550..2a25830e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedList.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedList.java @@ -57,6 +57,7 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad this.source = source; } + @Override public Object getSource() { return this.source; } @@ -83,10 +84,12 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad this.mergeEnabled = mergeEnabled; } + @Override public boolean isMergeEnabled() { return this.mergeEnabled; } + @Override @SuppressWarnings("unchecked") public List<E> merge(Object parent) { if (!this.mergeEnabled) { @@ -99,7 +102,7 @@ public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetad throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]"); } List<E> merged = new ManagedList<E>(); - merged.addAll((List) parent); + merged.addAll((List<E>) parent); merged.addAll(this); return merged; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedMap.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedMap.java index 4529b714..3cc4b986 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedMap.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedMap.java @@ -58,6 +58,7 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable, this.source = source; } + @Override public Object getSource() { return this.source; } @@ -98,10 +99,12 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable, this.mergeEnabled = mergeEnabled; } + @Override public boolean isMergeEnabled() { return this.mergeEnabled; } + @Override @SuppressWarnings("unchecked") public Object merge(Object parent) { if (!this.mergeEnabled) { @@ -114,7 +117,7 @@ public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable, throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]"); } Map<K, V> merged = new ManagedMap<K, V>(); - merged.putAll((Map) parent); + merged.putAll((Map<K, V>) parent); merged.putAll(this); return merged; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedProperties.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedProperties.java index 95b44472..dadaac3e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedProperties.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedProperties.java @@ -45,6 +45,7 @@ public class ManagedProperties extends Properties implements Mergeable, BeanMeta this.source = source; } + @Override public Object getSource() { return this.source; } @@ -57,11 +58,13 @@ public class ManagedProperties extends Properties implements Mergeable, BeanMeta this.mergeEnabled = mergeEnabled; } + @Override public boolean isMergeEnabled() { return this.mergeEnabled; } + @Override public Object merge(Object parent) { if (!this.mergeEnabled) { throw new IllegalStateException("Not allowed to merge when the 'mergeEnabled' property is set to 'false'"); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedSet.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedSet.java index 654cadc9..dc6f0e0c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedSet.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ManagedSet.java @@ -56,6 +56,7 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe this.source = source; } + @Override public Object getSource() { return this.source; } @@ -82,10 +83,12 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe this.mergeEnabled = mergeEnabled; } + @Override public boolean isMergeEnabled() { return this.mergeEnabled; } + @Override @SuppressWarnings("unchecked") public Set<E> merge(Object parent) { if (!this.mergeEnabled) { @@ -98,7 +101,7 @@ public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMe throw new IllegalArgumentException("Cannot merge with object of type [" + parent.getClass() + "]"); } Set<E> merged = new ManagedSet<E>(); - merged.addAll((Set) parent); + merged.addAll((Set<E>) parent); merged.addAll(this); return merged; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java index 33f969db..bf11af7e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/MethodOverride.java @@ -86,6 +86,7 @@ public abstract class MethodOverride implements BeanMetadataElement { this.source = source; } + @Override public Object getSource() { return this.source; } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReader.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReader.java index d51dc55f..454b2c35 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReader.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/PropertiesBeanDefinitionReader.java @@ -204,6 +204,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader * @throws BeanDefinitionStoreException in case of loading or parsing errors * @see #loadBeanDefinitions(org.springframework.core.io.Resource, String) */ + @Override public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException { return loadBeanDefinitions(new EncodedResource(resource), null); } @@ -289,9 +290,9 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader public int registerBeanDefinitions(ResourceBundle rb, String prefix) throws BeanDefinitionStoreException { // Simply create a map and call overloaded method. Map<String, Object> map = new HashMap<String, Object>(); - Enumeration keys = rb.getKeys(); + Enumeration<String> keys = rb.getKeys(); while (keys.hasMoreElements()) { - String key = (String) keys.nextElement(); + String key = keys.nextElement(); map.put(key, rb.getObject(key)); } return registerBeanDefinitions(map, prefix); @@ -308,7 +309,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader * @throws BeansException in case of loading or parsing errors * @see #registerBeanDefinitions(java.util.Map, String, String) */ - public int registerBeanDefinitions(Map map) throws BeansException { + public int registerBeanDefinitions(Map<?, ?> map) throws BeansException { return registerBeanDefinitions(map, null); } @@ -323,7 +324,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader * @return the number of bean definitions found * @throws BeansException in case of loading or parsing errors */ - public int registerBeanDefinitions(Map map, String prefix) throws BeansException { + public int registerBeanDefinitions(Map<?, ?> map, String prefix) throws BeansException { return registerBeanDefinitions(map, prefix, "Map " + map); } @@ -341,7 +342,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader * @throws BeansException in case of loading or parsing errors * @see #registerBeanDefinitions(Map, String) */ - public int registerBeanDefinitions(Map map, String prefix, String resourceDescription) + public int registerBeanDefinitions(Map<?, ?> map, String prefix, String resourceDescription) throws BeansException { if (prefix == null) { @@ -412,7 +413,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader ConstructorArgumentValues cas = new ConstructorArgumentValues(); MutablePropertyValues pvs = new MutablePropertyValues(); - for (Map.Entry entry : map.entrySet()) { + for (Map.Entry<?, ?> entry : map.entrySet()) { String key = StringUtils.trimWhitespace((String) entry.getKey()); if (key.startsWith(prefix + SEPARATOR)) { String property = key.substring(prefix.length() + SEPARATOR.length()); @@ -501,7 +502,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader * Reads the value of the entry. Correctly interprets bean references for * values that are prefixed with an asterisk. */ - private Object readValue(Map.Entry entry) { + private Object readValue(Map.Entry<? ,?> entry) { Object val = entry.getValue(); if (val instanceof String) { String strVal = (String) val; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java index 55ef696b..b3eb9b9e 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ReplaceOverride.java @@ -112,8 +112,7 @@ public class ReplaceOverride extends MethodOverride { @Override public String toString() { - return "Replace override for method '" + getMethodName() + "; will call bean '" + - this.methodReplacerBeanName + "'"; + return "Replace override for method '" + getMethodName() + "'"; } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java index c209e49f..d2ac971c 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/RootBeanDefinition.java @@ -61,6 +61,9 @@ public class RootBeanDefinition extends AbstractBeanDefinition { /** Package-visible field for caching the resolved constructor or factory method */ Object resolvedConstructorOrFactoryMethod; + /** Package-visible field for caching the return type of a generically typed factory method */ + volatile Class<?> resolvedFactoryMethodReturnType; + /** Package-visible field that marks the constructor arguments as resolved */ boolean constructorArgumentsResolved = false; @@ -110,33 +113,6 @@ public class RootBeanDefinition extends AbstractBeanDefinition { } /** - * Create a new RootBeanDefinition with the given singleton status. - * @param beanClass the class of the bean to instantiate - * @param singleton the singleton status of the bean - * @deprecated since Spring 2.5, in favor of {@link #setScope} - */ - @Deprecated - public RootBeanDefinition(Class beanClass, boolean singleton) { - super(); - setBeanClass(beanClass); - setSingleton(singleton); - } - - /** - * Create a new RootBeanDefinition for a singleton, - * using the given autowire mode. - * @param beanClass the class of the bean to instantiate - * @param autowireMode by name or type, using the constants in this interface - * @deprecated as of Spring 3.0, in favor of {@link #setAutowireMode} usage - */ - @Deprecated - public RootBeanDefinition(Class beanClass, int autowireMode) { - super(); - setBeanClass(beanClass); - setAutowireMode(autowireMode); - } - - /** * Create a new RootBeanDefinition for a singleton, * using the given autowire mode. * @param beanClass the class of the bean to instantiate @@ -155,34 +131,6 @@ public class RootBeanDefinition extends AbstractBeanDefinition { /** * Create a new RootBeanDefinition for a singleton, - * providing property values. - * @param beanClass the class of the bean to instantiate - * @param pvs the property values to apply - * @deprecated as of Spring 3.0, in favor of {@link #getPropertyValues} usage - */ - @Deprecated - public RootBeanDefinition(Class beanClass, MutablePropertyValues pvs) { - super(null, pvs); - setBeanClass(beanClass); - } - - /** - * Create a new RootBeanDefinition with the given singleton status, - * providing property values. - * @param beanClass the class of the bean to instantiate - * @param pvs the property values to apply - * @param singleton the singleton status of the bean - * @deprecated since Spring 2.5, in favor of {@link #setScope} - */ - @Deprecated - public RootBeanDefinition(Class beanClass, MutablePropertyValues pvs, boolean singleton) { - super(null, pvs); - setBeanClass(beanClass); - setSingleton(singleton); - } - - /** - * Create a new RootBeanDefinition for a singleton, * providing constructor arguments and property values. * @param beanClass the class of the bean to instantiate * @param cargs the constructor argument values to apply @@ -222,7 +170,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition { * @param original the original bean definition to copy from */ public RootBeanDefinition(RootBeanDefinition original) { - super((BeanDefinition) original); + super(original); this.allowCaching = original.allowCaching; this.decoratedDefinition = original.decoratedDefinition; this.targetType = original.targetType; @@ -239,10 +187,12 @@ public class RootBeanDefinition extends AbstractBeanDefinition { } + @Override public String getParentName() { return null; } + @Override public void setParentName(String parentName) { if (parentName != null) { throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference"); diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java index 735def66..4d29b95b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleAutowireCandidateResolver.java @@ -1,6 +1,5 @@ - /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,12 +36,19 @@ public class SimpleAutowireCandidateResolver implements AutowireCandidateResolve * <p>To be considered a candidate the bean's <em>autowire-candidate</em> * attribute must not have been set to 'false'. */ + @Override public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) { return bdHolder.getBeanDefinition().isAutowireCandidate(); } + @Override public Object getSuggestedValue(DependencyDescriptor descriptor) { return null; } + @Override + public Object getLazyResolutionProxyIfNecessary(DependencyDescriptor descriptor, String beanName) { + return null; + } + } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleBeanDefinitionRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleBeanDefinitionRegistry.java index 8a42fc23..b792c6cd 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleBeanDefinitionRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleBeanDefinitionRegistry.java @@ -40,6 +40,7 @@ public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64); + @Override public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { @@ -48,12 +49,14 @@ public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements this.beanDefinitionMap.put(beanName, beanDefinition); } + @Override public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { if (this.beanDefinitionMap.remove(beanName) == null) { throw new NoSuchBeanDefinitionException(beanName); } } + @Override public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { BeanDefinition bd = this.beanDefinitionMap.get(beanName); if (bd == null) { @@ -62,18 +65,22 @@ public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements return bd; } + @Override public boolean containsBeanDefinition(String beanName) { return this.beanDefinitionMap.containsKey(beanName); } + @Override public String[] getBeanDefinitionNames() { return StringUtils.toStringArray(this.beanDefinitionMap.keySet()); } + @Override public int getBeanDefinitionCount() { return this.beanDefinitionMap.size(); } + @Override public boolean isBeanNameInUse(String beanName) { return isAlias(beanName) || containsBeanDefinition(beanName); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java index cdc12a1d..26ef2127 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleInstantiationStrategy.java @@ -55,6 +55,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { } + @Override public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { // Don't override the class with CGLIB if no overrides. if (beanDefinition.getMethodOverrides().isEmpty()) { @@ -68,7 +69,8 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { } try { if (System.getSecurityManager() != null) { - constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() { + constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() { + @Override public Constructor<?> run() throws Exception { return clazz.getDeclaredConstructor((Class[]) null); } @@ -105,6 +107,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { "Method Injection not supported in SimpleInstantiationStrategy"); } + @Override public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, final Constructor<?> ctor, Object[] args) { @@ -112,6 +115,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { if (System.getSecurityManager() != null) { // use own privileged to change accessibility (when security is on) AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { ReflectionUtils.makeAccessible(ctor); return null; @@ -138,12 +142,14 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy { "Method Injection not supported in SimpleInstantiationStrategy"); } + @Override public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, Object[] args) { try { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override public Object run() { ReflectionUtils.makeAccessible(factoryMethod); return null; diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java index edb954ae..15aed4c5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/SimpleSecurityContextProvider.java @@ -51,6 +51,7 @@ public class SimpleSecurityContextProvider implements SecurityContextProvider { } + @Override public AccessControlContext getAccessControlContext() { return (this.acc != null ? acc : AccessController.getContext()); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java index 16681cc4..529fbd7d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/StaticListableBeanFactory.java @@ -76,6 +76,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory { // Implementation of BeanFactory interface //--------------------------------------------------------------------- + @Override public Object getBean(String name) throws BeansException { String beanName = BeanFactoryUtils.transformedBeanName(name); Object bean = this.beans.get(beanName); @@ -104,6 +105,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory { } } + @Override @SuppressWarnings("unchecked") public <T> T getBean(String name, Class<T> requiredType) throws BeansException { Object bean = getBean(name); @@ -113,6 +115,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory { return (T) bean; } + @Override public <T> T getBean(Class<T> requiredType) throws BeansException { String[] beanNames = getBeanNamesForType(requiredType); if (beanNames.length == 1) { @@ -126,6 +129,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory { } } + @Override public Object getBean(String name, Object... args) throws BeansException { if (args != null) { throw new UnsupportedOperationException( @@ -134,16 +138,19 @@ public class StaticListableBeanFactory implements ListableBeanFactory { return getBean(name); } + @Override public boolean containsBean(String name) { return this.beans.containsKey(name); } + @Override public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { Object bean = getBean(name); // In case of FactoryBean, return singleton status of created object. return (bean instanceof FactoryBean && ((FactoryBean<?>) bean).isSingleton()); } + @Override public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { Object bean = getBean(name); // In case of FactoryBean, return prototype status of created object. @@ -151,11 +158,13 @@ public class StaticListableBeanFactory implements ListableBeanFactory { (bean instanceof FactoryBean && !((FactoryBean<?>) bean).isSingleton())); } + @Override public boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException { Class<?> type = getType(name); return (targetType == null || (type != null && targetType.isAssignableFrom(type))); } + @Override public Class<?> getType(String name) throws NoSuchBeanDefinitionException { String beanName = BeanFactoryUtils.transformedBeanName(name); @@ -172,6 +181,7 @@ public class StaticListableBeanFactory implements ListableBeanFactory { return bean.getClass(); } + @Override public String[] getAliases(String name) { return new String[0]; } @@ -181,22 +191,27 @@ public class StaticListableBeanFactory implements ListableBeanFactory { // Implementation of ListableBeanFactory interface //--------------------------------------------------------------------- + @Override public boolean containsBeanDefinition(String name) { return this.beans.containsKey(name); } + @Override public int getBeanDefinitionCount() { return this.beans.size(); } + @Override public String[] getBeanDefinitionNames() { return StringUtils.toStringArray(this.beans.keySet()); } + @Override public String[] getBeanNamesForType(Class<?> type) { return getBeanNamesForType(type, true, true); } + @Override public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean includeFactoryBeans) { boolean isFactoryType = (type != null && FactoryBean.class.isAssignableFrom(type)); List<String> matches = new ArrayList<String>(); @@ -219,10 +234,12 @@ public class StaticListableBeanFactory implements ListableBeanFactory { return StringUtils.toStringArray(matches); } + @Override public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException { return getBeansOfType(type, true, true); } + @Override @SuppressWarnings("unchecked") public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean includeFactoryBeans) throws BeansException { @@ -259,6 +276,18 @@ public class StaticListableBeanFactory implements ListableBeanFactory { return matches; } + @Override + public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) { + List<String> results = new ArrayList<String>(); + for (String beanName : this.beans.keySet()) { + if (findAnnotationOnBean(beanName, annotationType) != null) { + results.add(beanName); + } + } + return results.toArray(new String[results.size()]); + } + + @Override public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException { @@ -271,7 +300,10 @@ public class StaticListableBeanFactory implements ListableBeanFactory { return results; } - public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) { + @Override + public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType) + throws NoSuchBeanDefinitionException{ + return AnnotationUtils.findAnnotation(getType(beanName), annotationType); } |