1. 程式人生 > >Spring原始碼學習筆記之bean標籤屬性介紹及作用

Spring原始碼學習筆記之bean標籤屬性介紹及作用

 傳統的Spring專案, xml 配置bean在程式碼中是經常遇到, 那麼在配置bean的時候,這些屬性的作用是什麼呢? 
雖然說現在boot專案興起,基於xml配置的少了很多, 但是如果能夠了解這些標籤的作用對於我們基於註解的配置也有大有益處的.

首先附上測試部分涉及到的類的程式碼:
@Data
public class Student {

    private int age;

    private  String name = "test" ;

    private int sex;
}

  

1. id:Bean的唯一標識名。它必須是合法的XMLID,在整個XML文件中唯一。

 

 

 

2. name:用來為id建立一個或多個別名。它可以是任意的字母符合。多個別名之間用逗號, 分號 或者空格。

 

 

 其中bean標籤解析原始碼部分處理程式碼如下:

 

    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//解析nanme 屬性,
// 其中 public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; ";
// 我們可以發現name屬性的分割符是支援三種的
List<String> aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) {
// 使用分割符分割為陣列, 作為這個bean的別名 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id;
// 如果id 屬性為空,則講第一個別名作為bean的名稱 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { beanName = aliases.remove(0); if (logger.isTraceEnabled()) { logger.trace("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName( beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); // Register an alias for the plain bean class name, if still possible, // if the generator returned the class name plus a suffix. // This is expected for Spring 1.2/2.0 backwards compatibility. String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { aliases.add(beanClassName); } } if (logger.isTraceEnabled()) { logger.trace("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }


3. class:用來定義類的全限定名(包名+類名)。用來指定我們要例項化的類的全限定名

4. parent:子類Bean定義它所引用它的父類Bean。子類Bean會繼承父類Bean的所有屬性,子類Bean也可以覆蓋父類Bean的屬性。
此時父類通過property 屬性只能初始化子類同有的屬性


5. abstract(預設為”false”):用來定義Bean是否為抽象Bean。它表示這個Bean將不會被例項化,一般用於父類Bean,因為父類Bean主要是供子類Bean繼承使用。

<bean id="parent" class="com.cbl.spring.model.Parent" abstract="true">
<property name="username" value="parent name"/>
<!-- <property name="parent" value="parent "/>-->
</bean>
// 這裡abstract設定為了 true ,這個parentbean不會被例項化, 一下程式碼會報錯
Parent parent = applicationContext.getBean(Parent.class);

屬性解析部分原始碼:
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
            @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
          
// singleton 屬性新版本不再有起任何作用, 1.x 的老版本中有使用到, 新版本使用scope 屬性 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); } else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); } else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition. bd.setScope(containingBean.getScope()); } if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); } String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) { String candidatePattern = this.defaults.getAutowireCandidates(); if (candidatePattern != null) { String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); } if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); bd.setInitMethodName(initMethodName); } else if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); bd.setDestroyMethodName(destroyMethodName); } else if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); } if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); } return bd; }//beanDifinition 的部分屬性預設值定義
public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccessor
        implements BeanDefinition, Cloneable {

    /**
     * Constant for the default scope name: {@code ""}, equivalent to singleton
     * status unless overridden from a parent bean definition (if applicable).
     */

// 預設值是空,等同於singleton ,除非被父類給覆蓋,也就是說預設值時 singleton public static final String SCOPE_DEFAULT = ""; /** * Constant that indicates no autowiring at all. * @see #setAutowireMode */ public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO; /** * Constant that indicates autowiring bean properties by name. * @see #setAutowireMode */ public static final int AUTOWIRE_BY_NAME = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; /** * Constant that indicates autowiring bean properties by type. * @see #setAutowireMode */ public static final int AUTOWIRE_BY_TYPE = AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE; /** * Constant that indicates autowiring a constructor. * @see #setAutowireMode */ public static final int AUTOWIRE_CONSTRUCTOR = AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR; /** * Constant that indicates determining an appropriate autowire strategy * through introspection of the bean class. * @see #setAutowireMode * @deprecated as of Spring 3.0: If you are using mixed autowiring strategies, * use annotation-based autowiring for clearer demarcation of autowiring needs. */ @Deprecated public static final int AUTOWIRE_AUTODETECT = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT; /** * Constant that indicates no dependency check at all. * @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_NONE = 0; /** * Constant that indicates dependency checking for object references. * @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_OBJECTS = 1; /** * Constant that indicates dependency checking for "simple" properties. * @see #setDependencyCheck * @see org.springframework.beans.BeanUtils#isSimpleProperty */ public static final int DEPENDENCY_CHECK_SIMPLE = 2; /** * Constant that indicates dependency checking for all properties * (object references as well as "simple" properties). * @see #setDependencyCheck */ public static final int DEPENDENCY_CHECK_ALL = 3; /** * Constant that indicates the container should attempt to infer the * {@link #setDestroyMethodName destroy method name} for a bean as opposed to * explicit specification of a method name. The value {@value} is specifically * designed to include characters otherwise illegal in a method name, ensuring * no possibility of collisions with legitimately named methods having the same * name. * <p>Currently, the method names detected during destroy method inference * are "close" and "shutdown", if present on the specific bean class. */ public static final String INFER_METHOD = "(inferred)"; @Nullable private volatile Object beanClass; @Nullable private String scope = SCOPE_DEFAULT; private boolean abstractFlag = false;
// 懶載入的預設值時false private boolean lazyInit = false; private int autowireMode = AUTOWIRE_NO; private int dependencyCheck = DEPENDENCY_CHECK_NONE; @Nullable private String[] dependsOn; private boolean autowireCandidate = true; private boolean primary = false; private final Map<String, AutowireCandidateQualifier> qualifiers = new LinkedHashMap<>(); @Nullable private Supplier<?> instanceSupplier; private boolean nonPublicAccessAllowed = true; private boolean lenientConstructorResolution = true; @Nullable private String factoryBeanName; @Nullable private String factoryMethodName; @Nullable private ConstructorArgumentValues constructorArgumentValues; @Nullable private MutablePropertyValues propertyValues; @Nullable private MethodOverrides methodOverrides; @Nullable private String initMethodName; @Nullable private String destroyMethodName; private boolean enforceInitMethod = true; private boolean enforceDestroyMethod = true; private boolean synthetic = false; }

 




6. singleton(預設為“true”):定義Bean是否是Singleton(單例)。
singleton 屬性新版本不再有起任何作用, 1.x 的老版本中有使用到, 新版本使用scope 屬性

7.lazy-init(預設為“false”):用來定義這個Bean是否實現懶初始化。如果為“false”,它將在BeanFactory啟動時初始化所有的SingletonBean。反之,如果為“true”,它只在Bean請求時才開始建立SingletonBean。

預設建立的beandefinition 物件是 GenericBeanDefinition, 而 GenericBeanDefinition 繼承自 AbstractBeanDefinition ,那麼我們的預設的一些屬性必然就使用的這兩個類中提供的預設值,從上面的部分成員變數的屬性值可以看出,預設值為false

8、autowire(自動裝配,預設為“default”):它定義了Bean的自動裝載方式。

8.1、“no”:不使用自動裝配功能。

8.2、“byName”:通過Bean的屬性名實現自動裝配。

8.3、“byType”:通過Bean的型別實現自動裝配。

8.4、“constructor”:類似於byType,但它是用於建構函式的引數的自動組裝。

8.5、“autodetect”:通過Bean類的反省機制(introspection)決定是使用“constructor” 還是使用“byType”。

9、dependency-check(依賴檢查,預設為“default”):它用來確保Bean元件通過JavaBean描述的所以依賴關係都得到滿足。在與自動裝配功能一起使用時,它特別有用。

9.1、none:不進行依賴檢查。

9.2、objects:只做物件間依賴的檢查。

9.3、simple:只做原始型別和String型別依賴的檢查

9.4、all:對所有型別的依賴進行檢查。它包括了前面的objects和simple。

10、depends-on(依賴物件):這個Bean在初始化時依賴的物件,這個物件會在這個Bean初始化之前建立。

11、init-method:用來定義Bean的初始化方法,它會在Bean組裝之後呼叫。它必須是一個無引數的方法。

12、destroy-method:用來定義Bean的銷燬方法,它在BeanFactory關閉時呼叫。同樣,它也必須是一個無引數的方法。它只能應用於singletonBean。

13、factory-method:定義建立該Bean物件的工廠方法。它用於下面的“factory-bean”,表示這個Bean是通過工廠方法建立。此時,“class”屬性失效。

14、factory-bean:定義建立該Bean物件的工廠類。如果使用了“factory-bean”則“class”屬性失效。

15、autowire-candidate:採用xml格式配置bean時,將<bean/>元素的autowire-candidate屬性設定為false,這樣容器在查詢自動裝配物件時,將不考慮該bean,即它不會被考慮作為其它bean自動裝配的候選者,但是該bean本身還是可以使用自動裝配來注入其它bean的