Spring之核心BeanDefinition

BeanDifinitionjava

1. 接口類

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

	String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

	String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

	int ROLE_APPLICATION = 0;

	int ROLE_SUPPORT = 1;

	int ROLE_INFRASTRUCTURE = 2;

	String getParentName();

	void setParentName(String parentName);

	String getBeanClassName();

	void setBeanClassName(String beanClassName);

	String getFactoryBeanName();

	void setFactoryBeanName(String factoryBeanName);

	
	String getFactoryMethodName();

	void setFactoryMethodName(String factoryMethodName);

	String getScope();

	void setScope(String scope);

	boolean isLazyInit();


	void setLazyInit(boolean lazyInit);

	String[] getDependsOn();

	void setDependsOn(String... dependsOn);

	boolean isAutowireCandidate();

	void setAutowireCandidate(boolean autowireCandidate);


	boolean isPrimary();


	void setPrimary(boolean primary);


	ConstructorArgumentValues getConstructorArgumentValues();

	
	MutablePropertyValues getPropertyValues();


	boolean isSingleton();

	boolean isPrototype();

	boolean isAbstract();

	int getRole();

	String getDescription();

	String getResourceDescription();


	BeanDefinition getOriginatingBeanDefinition();

}

複製代碼

2.BeanDefinition是描述bean元數據定義信息的接口定義

接口能夠獲得bean的Class,bean的做用域、是否爲懶加載、依賴的bean、構造參數、屬性值等
能夠想象咱們在xml配置的bean屬性等確定性須要封裝存儲在一個地方,那麼BeanDefinition就是封裝bean屬性的定義。在java中咱們全部的類定義都是在class文件中,經過jvm加載。在spring中就是經過xml或者註解定義,轉化爲BeanDefinition定義,經過spring ioc模塊生成具體的bean

3.實現類結構圖

BeanDefinition

BeanDefinition接口繼承了兩個接口AttributeAccessor、BeanMetadataElement, 從名字能夠看出

AttributeAccessor是屬性存儲器,一些非bean的公共配置項的存儲就須要藉助此接口來存儲spring

BeanMetadataElement 能夠獲取bean元數據的配置源dom

AbstractBeanDefinition

是BeanDefinition的抽象實現,其實已經基本實現了所有功能,繼承了BeanMetadataAttributeAccessor, 此類是前面兩個接口的具體實現,這樣賦予了AbstractBeanDefinition兩個接口的真正能力

RootBeanDefinition

是一個根bean定義,它不能有父bean定義。父子定義是spring的bean配置的一個繼承關係

ChildBeanDefinition

子bean定義,必須有父bean定義,其餘徹底是抽象類的功能實現

GenericBeanDefinition

通用的bean定義實現,也是目前默認建立的實現

4.spring中父子bean配置繼承關係

java中的繼承關係是經過extends關鍵字進行關聯
spring中能夠經過xml配置parent進行繼承置項
<!-- 父子bean 測試xml -->
    <bean id="parent" abstract="true">    
        <property name="name" value="爹"></property>
    </bean>

    <bean id="child" parent="parent" lass="spring.domain.Bean">
    </bean>

複製代碼
ClassPathXmlApplicationContext cpa = new ClassPathXmlApplicationContext("/spring/spring-config.xml");
        cpa.refresh();

        System.out.println(JSON.toJSONString(cpa.getBean("child")));
        cpa.destroy();
複製代碼
運行後能夠發現child的bean 其中的name屬性是爹,child繼承了parent的配置屬性

源碼觀察

// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
					boolean isEagerInit;
					if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
						isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
							@Override
							public Boolean run() {
								return ((SmartFactoryBean<?>) factory).isEagerInit();
							}
						}, getAccessControlContext());
					}
					else {
						isEagerInit = (factory instanceof SmartFactoryBean &&
								((SmartFactoryBean<?>) factory).isEagerInit());
					}
					if (isEagerInit) {
						getBean(beanName);
					}
				}
				else {
					getBean(beanName);
				}
			}
		}
複製代碼
preInstantiateSingletons開始觸發生成bean方法時,遍歷全部beanNames,對於每個beanName都須要經過#getMergedLocalBeanDefinition 方法來拿到最終的BeanDefinition, 這個方法作了什麼呢?
protected RootBeanDefinition getMergedBeanDefinition( String beanName, BeanDefinition bd, BeanDefinition containingBd) throws BeanDefinitionStoreException {

		synchronized (this.mergedBeanDefinitions) {
			RootBeanDefinition mbd = null;

			// Check with full lock now in order to enforce the same merged instance.
			if (containingBd == null) {
				mbd = this.mergedBeanDefinitions.get(beanName);
			}

			if (mbd == null) {
				if (bd.getParentName() == null) {
					// Use copy of given root bean definition.
					if (bd instanceof RootBeanDefinition) {
						mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
					}
					else {
						mbd = new RootBeanDefinition(bd);
					}
				}
				else {
					// Child bean definition: needs to be merged with parent.
					BeanDefinition pbd;
					try {
						String parentBeanName = transformedBeanName(bd.getParentName());
                        //若是父類和當前類的名稱不同本容器查找
						if (!beanName.equals(parentBeanName)) {
							pbd = getMergedBeanDefinition(parentBeanName);
						}
						else {//不然從父容器中查找
							if (getParentBeanFactory() instanceof ConfigurableBeanFactory) {
								pbd = ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(parentBeanName);
							}
							else {
								throw new NoSuchBeanDefinitionException(bd.getParentName(),
										"Parent name '" + bd.getParentName() + "' is equal to bean name '" + beanName +
										"': cannot be resolved without an AbstractBeanFactory parent");
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
								"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
					}
					// Deep copy with overridden values.
                 // 先生成一個父類屬性的Root,再用子類屬性覆蓋
					mbd = new RootBeanDefinition(pbd);
					mbd.overrideFrom(bd);
				}

				// Set default singleton scope, if not configured before.
				if (!StringUtils.hasLength(mbd.getScope())) {
					mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
				}

				// A bean contained in a non-singleton bean cannot be a singleton itself.
				// Let's correct this on the fly here, since this might be the result of
				// parent-child merging for the outer bean, in which case the original inner bean
				// definition will not have inherited the merged outer bean's singleton status.
				if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
					mbd.setScope(containingBd.getScope());
				}

				// Only cache the merged bean definition if we're already about to create an
				// instance of the bean, or at least have already created an instance before.
				if (containingBd == null && isCacheBeanMetadata()) {
					this.mergedBeanDefinitions.put(beanName, mbd);
				}
			}

			return mbd;
		}
	}
複製代碼
能夠看到根據beanDefinition中的parentName獲取到父BeanDefinition,遞歸獲取,而且子類覆蓋父類,最終獲得一個全部配置項合併的BeanDefinition, 用這個RootBeanDefinition進行初始化bean
相關文章
相關標籤/搜索