提交 e8a082fb 编写于 作者: J Juergen Hoeller

Clarified setAutowireCandidate semantics (plus attribute reordering in BeanDefinition)

Issue: SPR-15072
上级 ccabff6b
......@@ -79,10 +79,7 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
int ROLE_INFRASTRUCTURE = 2;
/**
* Return the name of the parent definition of this bean definition, if any.
*/
String getParentName();
// Modifiable attributes
/**
* Set the name of the parent definition of this bean definition, if any.
......@@ -90,46 +87,40 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
void setParentName(String parentName);
/**
* Return the current bean class name of this bean definition.
* <p>Note that this does not have to be the actual class name used at runtime, in
* case of a child definition overriding/inheriting the class name from its parent.
* Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
* rather only use it for parsing purposes at the individual bean definition level.
* Return the name of the parent definition of this bean definition, if any.
*/
String getBeanClassName();
String getParentName();
/**
* Override the bean class name of this bean definition.
* Specify the bean class name of this bean definition.
* <p>The class name can be modified during bean factory post-processing,
* typically replacing the original class name with a parsed variant of it.
* @see #setParentName
* @see #setFactoryBeanName
* @see #setFactoryMethodName
*/
void setBeanClassName(String beanClassName);
/**
* Return the factory bean name, if any.
*/
String getFactoryBeanName();
/**
* Specify the factory bean to use, if any.
*/
void setFactoryBeanName(String factoryBeanName);
/**
* Return a factory method, if any.
* Return the current bean class name of this bean definition.
* <p>Note that this does not have to be the actual class name used at runtime, in
* case of a child definition overriding/inheriting the class name from its parent.
* Also, this may just be the class that a factory method is called on, or it may
* even be empty in case of a factory bean reference that a method is called on.
* Hence, do <i>not</i> consider this to be the definitive bean type at runtime but
* rather only use it for parsing purposes at the individual bean definition level.
* @see #getParentName()
* @see #getFactoryBeanName()
* @see #getFactoryMethodName()
*/
String getFactoryMethodName();
String getBeanClassName();
/**
* Specify a factory method, if any. This method will be invoked with
* constructor arguments, or with no arguments if none are specified.
* The method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @param factoryMethodName static factory method name,
* or {@code null} if normal constructor creation should be used
* @see #getBeanClassName()
* Override the target scope of this bean, specifying a new scope name.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
*/
void setFactoryMethodName(String factoryMethodName);
void setScope(String scope);
/**
* Return the name of the current target scope for this bean,
......@@ -138,11 +129,11 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String getScope();
/**
* Override the target scope of this bean, specifying a new scope name.
* @see #SCOPE_SINGLETON
* @see #SCOPE_PROTOTYPE
* Set whether this bean should be lazily initialized.
* <p>If {@code false}, the bean will get instantiated on startup by bean
* factories that perform eager initialization of singletons.
*/
void setScope(String scope);
void setLazyInit(boolean lazyInit);
/**
* Return whether this bean should be lazily initialized, i.e. not
......@@ -151,11 +142,10 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
boolean isLazyInit();
/**
* Set whether this bean should be lazily initialized.
* <p>If {@code false}, the bean will get instantiated on startup by bean
* factories that perform eager initialization of singletons.
* Set the names of the beans that this bean depends on being initialized.
* The bean factory will guarantee that these beans get initialized first.
*/
void setLazyInit(boolean lazyInit);
void setDependsOn(String... dependsOn);
/**
* Return the bean names that this bean depends on.
......@@ -163,10 +153,13 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
String[] getDependsOn();
/**
* Set the names of the beans that this bean depends on being initialized.
* The bean factory will guarantee that these beans get initialized first.
* Set whether this bean is a candidate for getting autowired into some other bean.
* <p>Note that this flag is designed to only affect type-based autowiring.
* It does not affect explicit references by name, which will get resolved even
* if the specified bean is not marked as an autowire candidate. As a consequence,
* autowiring by name will nevertheless inject a bean if the name matches.
*/
void setDependsOn(String... dependsOn);
void setAutowireCandidate(boolean autowireCandidate);
/**
* Return whether this bean is a candidate for getting autowired into some other bean.
......@@ -174,24 +167,43 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
boolean isAutowireCandidate();
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
* Set whether this bean is a primary autowire candidate.
* <p>If this value is {@code true} for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
void setAutowireCandidate(boolean autowireCandidate);
void setPrimary(boolean primary);
/**
* Return whether this bean is a primary autowire candidate.
* If this value is true for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
boolean isPrimary();
/**
* Set whether this bean is a primary autowire candidate.
* <p>If this value is true for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
* Specify the factory bean to use, if any.
* This the name of the bean to call the specified factory method on.
* @see #setFactoryMethodName
*/
void setPrimary(boolean primary);
void setFactoryBeanName(String factoryBeanName);
/**
* Return the factory bean name, if any.
*/
String getFactoryBeanName();
/**
* Specify a factory method, if any. This method will be invoked with
* constructor arguments, or with no arguments if none are specified.
* The method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @see #setFactoryBeanName
* @see #setBeanClassName
*/
void setFactoryMethodName(String factoryMethodName);
/**
* Return a factory method, if any.
*/
String getFactoryMethodName();
/**
* Return the constructor argument values for this bean.
......@@ -208,6 +220,8 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
MutablePropertyValues getPropertyValues();
// Read-only attributes
/**
* Return whether this a <b>Singleton</b>, with a single, shared instance
* returned on all calls.
......
......@@ -49,6 +49,7 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Rob Harrop
* @author Mark Fisher
* @see GenericBeanDefinition
* @see RootBeanDefinition
* @see ChildBeanDefinition
*/
......@@ -153,25 +154,24 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
private boolean primary = false;
private final Map<String, AutowireCandidateQualifier> qualifiers =
new LinkedHashMap<>(0);
private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(0);
private Supplier<?> instanceSupplier;
private boolean nonPublicAccessAllowed = true;
private boolean lenientConstructorResolution = true;
private String factoryBeanName;
private String factoryMethodName;
private ConstructorArgumentValues constructorArgumentValues;
private MutablePropertyValues propertyValues;
private MethodOverrides methodOverrides = new MethodOverrides();
private Supplier<?> instanceSupplier;
private String factoryBeanName;
private String factoryMethodName;
private String initMethodName;
private String destroyMethodName;
......@@ -213,14 +213,14 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
protected AbstractBeanDefinition(BeanDefinition original) {
setParentName(original.getParentName());
setBeanClassName(original.getBeanClassName());
setFactoryBeanName(original.getFactoryBeanName());
setFactoryMethodName(original.getFactoryMethodName());
setScope(original.getScope());
setAbstract(original.isAbstract());
setLazyInit(original.isLazyInit());
setRole(original.getRole());
setFactoryBeanName(original.getFactoryBeanName());
setFactoryMethodName(original.getFactoryMethodName());
setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
setRole(original.getRole());
setSource(original.getSource());
copyAttributesFrom(original);
......@@ -233,16 +233,16 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
setDependencyCheck(originalAbd.getDependencyCheck());
setDependsOn(originalAbd.getDependsOn());
setAutowireCandidate(originalAbd.isAutowireCandidate());
copyQualifiersFrom(originalAbd);
setPrimary(originalAbd.isPrimary());
copyQualifiersFrom(originalAbd);
setInstanceSupplier(originalAbd.getInstanceSupplier());
setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
setInstanceSupplier(originalAbd.getInstanceSupplier());
setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
setInitMethodName(originalAbd.getInitMethodName());
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
setDestroyMethodName(originalAbd.getDestroyMethodName());
setEnforceDestroyMethod(originalAbd.isEnforceDestroyMethod());
setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
setSynthetic(originalAbd.isSynthetic());
setResource(originalAbd.getResource());
}
......@@ -272,20 +272,20 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
if (StringUtils.hasLength(other.getBeanClassName())) {
setBeanClassName(other.getBeanClassName());
}
if (StringUtils.hasLength(other.getScope())) {
setScope(other.getScope());
}
setAbstract(other.isAbstract());
setLazyInit(other.isLazyInit());
if (StringUtils.hasLength(other.getFactoryBeanName())) {
setFactoryBeanName(other.getFactoryBeanName());
}
if (StringUtils.hasLength(other.getFactoryMethodName())) {
setFactoryMethodName(other.getFactoryMethodName());
}
if (StringUtils.hasLength(other.getScope())) {
setScope(other.getScope());
}
setAbstract(other.isAbstract());
setLazyInit(other.isLazyInit());
setRole(other.getRole());
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
getPropertyValues().addPropertyValues(other.getPropertyValues());
setRole(other.getRole());
setSource(other.getSource());
copyAttributesFrom(other);
......@@ -294,15 +294,16 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
if (otherAbd.hasBeanClass()) {
setBeanClass(otherAbd.getBeanClass());
}
setAutowireCandidate(otherAbd.isAutowireCandidate());
setAutowireMode(otherAbd.getAutowireMode());
copyQualifiersFrom(otherAbd);
setPrimary(otherAbd.isPrimary());
setDependencyCheck(otherAbd.getDependencyCheck());
setDependsOn(otherAbd.getDependsOn());
setAutowireCandidate(otherAbd.isAutowireCandidate());
setPrimary(otherAbd.isPrimary());
copyQualifiersFrom(otherAbd);
setInstanceSupplier(otherAbd.getInstanceSupplier());
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
setInstanceSupplier(otherAbd.getInstanceSupplier());
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
if (StringUtils.hasLength(otherAbd.getInitMethodName())) {
setInitMethodName(otherAbd.getInitMethodName());
setEnforceInitMethod(otherAbd.isEnforceInitMethod());
......@@ -311,7 +312,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
setDestroyMethodName(otherAbd.getDestroyMethodName());
setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
}
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
setSynthetic(otherAbd.isSynthetic());
setResource(otherAbd.getResource());
}
......@@ -336,10 +336,25 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Return whether this definition specifies a bean class.
* Specify the bean class name of this bean definition.
*/
public boolean hasBeanClass() {
return (this.beanClass instanceof Class);
@Override
public void setBeanClassName(String beanClassName) {
this.beanClass = beanClassName;
}
/**
* Return the current bean class name of this bean definition.
*/
@Override
public String getBeanClassName() {
Object beanClassObject = this.beanClass;
if (beanClassObject instanceof Class) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
}
/**
......@@ -367,20 +382,11 @@ 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) {
return ((Class<?>) beanClassObject).getName();
}
else {
return (String) beanClassObject;
}
/**
* Return whether this definition specifies a bean class.
*/
public boolean hasBeanClass() {
return (this.beanClass instanceof Class);
}
/**
......@@ -401,7 +407,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
return resolvedClass;
}
/**
* Set the name of the target scope for the bean.
* <p>The default is singleton status, although this is only applied once
......@@ -483,7 +488,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
return this.lazyInit;
}
/**
* Set the autowire mode. This determines whether any automagical detection
* and setting of bean references will happen. Default is AUTOWIRE_NO,
......@@ -574,6 +578,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Set whether this bean is a candidate for getting autowired into some other bean.
* <p>Note that this flag is designed to only affect type-based autowiring.
* It does not affect explicit references by name, which will get resolved even
* if the specified bean is not marked as an autowire candidate. As a consequence,
* autowiring by name will nevertheless inject a bean if the name matches.
* @see #AUTOWIRE_BY_TYPE
* @see #AUTOWIRE_BY_NAME
*/
@Override
public void setAutowireCandidate(boolean autowireCandidate) {
......@@ -590,7 +600,7 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Set whether this bean is a primary autowire candidate.
* If this value is true for exactly one bean among multiple
* <p>If this value is {@code true} for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
@Override
......@@ -600,8 +610,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
/**
* Return whether this bean is a primary autowire candidate.
* If this value is true for exactly one bean among multiple
* matching candidates, it will serve as a tie-breaker.
*/
@Override
public boolean isPrimary() {
......@@ -648,6 +656,27 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
this.qualifiers.putAll(source.qualifiers);
}
/**
* Specify a callback for creating an instance of the bean,
* as an alternative to a declaratively specified factory method.
* <p>If such a callback is set, it will override any other constructor
* or factory method metadata. However, bean property population and
* potential annotation-driven injection will still apply as usual.
* @since 5.0
* @see #setConstructorArgumentValues(ConstructorArgumentValues)
* @see #setPropertyValues(MutablePropertyValues)
*/
public void setInstanceSupplier(Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
/**
* Return a callback for creating an instance of the bean, if any.
* @since 5.0
*/
public Supplier<?> getInstanceSupplier() {
return this.instanceSupplier;
}
/**
* Specify whether to allow access to non-public constructors and methods,
......@@ -688,6 +717,45 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
return this.lenientConstructorResolution;
}
/**
* Specify the factory bean to use, if any.
* This the name of the bean to call the specified factory method on.
* @see #setFactoryMethodName
*/
@Override
public void setFactoryBeanName(String factoryBeanName) {
this.factoryBeanName = factoryBeanName;
}
/**
* Return the factory bean name, if any.
*/
@Override
public String getFactoryBeanName() {
return this.factoryBeanName;
}
/**
* Specify a factory method, if any. This method will be invoked with
* constructor arguments, or with no arguments if none are specified.
* The method will be invoked on the specified factory bean, if any,
* or otherwise as a static method on the local bean class.
* @see #setFactoryBeanName
* @see #setBeanClassName
*/
@Override
public void setFactoryMethodName(String factoryMethodName) {
this.factoryMethodName = factoryMethodName;
}
/**
* Return a factory method, if any.
*/
@Override
public String getFactoryMethodName() {
return this.factoryMethodName;
}
/**
* Specify constructor argument values for this bean.
*/
......@@ -742,49 +810,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
return this.methodOverrides;
}
/**
* Specify a callback for creating an instance of the bean,
* as an alternative to a declaratively specified factory method.
* <p>If such a callback is set, it will override any other constructor
* or factory method metadata. However, bean property population and
* potential annotation-driven injection will still apply as usual.
* @since 5.0
* @see #setConstructorArgumentValues(ConstructorArgumentValues)
* @see #setPropertyValues(MutablePropertyValues)
*/
public void setInstanceSupplier(Supplier<?> instanceSupplier) {
this.instanceSupplier = instanceSupplier;
}
/**
* Return a callback for creating an instance of the bean, if any.
* @since 5.0
*/
public Supplier<?> getInstanceSupplier() {
return this.instanceSupplier;
}
@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;
}
/**
* Set the name of the initializer method. The default is {@code null}
* in which case there is no initializer method.
......@@ -849,7 +874,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
return this.enforceDestroyMethod;
}
/**
* Set whether this bean definition is 'synthetic', that is, not defined
* by the application itself (for example, an infrastructure bean such
......@@ -882,7 +906,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
return this.role;
}
/**
* Set a human-readable description of this bean definition.
*/
......@@ -890,6 +913,9 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
this.description = description;
}
/**
* Return a human-readable description of this bean definition.
*/
@Override
public String getDescription() {
return this.description;
......@@ -918,6 +944,10 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
this.resource = new DescriptiveResource(resourceDescription);
}
/**
* Return a description of the resource that this bean definition
* came from (for the purpose of showing context in case of errors).
*/
@Override
public String getResourceDescription() {
return (this.resource != null ? this.resource.getDescription() : null);
......@@ -930,6 +960,12 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
this.resource = new BeanDefinitionResource(originatingBd);
}
/**
* Return the originating BeanDefinition, or {@code null} if none.
* Allows for retrieving the decorated bean definition, if any.
* <p>Note that this method returns the immediate originator. Iterate through the
* originator chain to find the original BeanDefinition as defined by the user.
*/
@Override
public BeanDefinition getOriginatingBeanDefinition() {
return (this.resource instanceof BeanDefinitionResource ?
......@@ -1008,7 +1044,6 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
*/
public abstract AbstractBeanDefinition cloneBeanDefinition();
@Override
public boolean equals(Object other) {
if (this == other) {
......
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
......@@ -53,10 +53,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
* configured through its bean properties and configuration methods.
* @param parentName the name of the parent bean
* @see #setBeanClass
* @see #setBeanClassName
* @see #setScope
* @see #setAutowireMode
* @see #setDependencyCheck
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
......@@ -174,9 +171,7 @@ public class ChildBeanDefinition extends AbstractBeanDefinition {
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Child bean with parent '");
sb.append(this.parentName).append("': ").append(super.toString());
return sb.toString();
return "Child bean with parent '" + this.parentName + "': " + super.toString();
}
}
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2016 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,10 +45,7 @@ public class GenericBeanDefinition extends AbstractBeanDefinition {
* Create a new GenericBeanDefinition, to be configured through its bean
* properties and configuration methods.
* @see #setBeanClass
* @see #setBeanClassName
* @see #setScope
* @see #setAutowireMode
* @see #setDependencyCheck
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
......
......@@ -103,10 +103,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* Create a new RootBeanDefinition, to be configured through its bean
* properties and configuration methods.
* @see #setBeanClass
* @see #setBeanClassName
* @see #setScope
* @see #setAutowireMode
* @see #setDependencyCheck
* @see #setConstructorArgumentValues
* @see #setPropertyValues
*/
......@@ -131,7 +128,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* @param instanceSupplier the supplier to construct a bean instance,
* as an alternative to a declaratively specified factory method
* @since 5.0
* @see #setInstanceSupplier(Supplier)
* @see #setInstanceSupplier
*/
public <T> RootBeanDefinition(Class<T> beanClass, Supplier<T> instanceSupplier) {
super();
......@@ -147,7 +144,7 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
* @param instanceSupplier the supplier to construct a bean instance,
* as an alternative to a declaratively specified factory method
* @since 5.0
* @see #setInstanceSupplier(Supplier)
* @see #setInstanceSupplier
*/
public <T> RootBeanDefinition(Class<T> beanClass, String scope, Supplier<T> instanceSupplier) {
super();
......
......@@ -2002,6 +2002,14 @@ makes that specific bean definition unavailable to the autowiring infrastructure
(including annotation style configurations such as <<beans-autowired-annotation,
`@Autowired`>>).
[NOTE]
====
The `autowire-candidate` attribute is designed to only affect type-based autowiring.
It does not affect explicit references by name, which will get resolved even if the
specified bean is not marked as an autowire candidate. As a consequence, autowiring
by name will nevertheless inject a bean if the name matches.
====
You can also limit autowire candidates based on pattern-matching against bean names. The
top-level `<beans/>` element accepts one or more patterns within its
`default-autowire-candidates` attribute. For example, to limit autowire candidate status
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册