一個Spring Bean從無到有的過程

有開頭沒結尾

      經歷了java開發變遷史,從早期編寫原生的servlet、自研mvc和jdbc工具、和使用開源框架struts、hibernate、jsp、spring、springmvc、freemarker、springboot,到最後前後端分離式開發,一開始開發工具用的是editplus。相對來說,現在開發很好了,框架生態(只有spring生態傳承下來了,其他都成了歷史)。到spring生態圈終結了,它的體系太過龐大了,席捲了各國,項目產品技術換型的機率很小了。

      一開始做Spring相關開發,寫了大量xml配置,到後來換成了註解式開發,雖然能幹活,可並不知道它的內在原理和設計理念是什麼,隨着時間的累計,需要做sping 擴展或集成,就要研究源碼級是如何實現的了。我就以一個Spring Bean如何創建開始,不要小看一個Bean,很多碼農都說不清它的創建過程。

簡單介紹Spring框架是一個開放源代碼的J2EE應用程序框架,由Rod Johnson發起,是針對bean的生命週期進行管理的輕量級容器(lightweight container)。 Spring解決了開發者在J2EE開發中遇到的許多常見的問題,提供了功能強大IOC、AOP及Web MVC等功能。Spring可以單獨應用於構築應用程序,也可以和Struts、Webwork、Tapestry等衆多Web框架組合使用,並且可以與 Swing等桌面應用程序AP組合。因此, Spring不僅僅能應用於JEE應用程序之中,也可以應用於桌面應用程序以及小應用程序之中。Spring框架主要由七部分組成,分別是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

就是圖片裏的Beans,下面開始進入正題,看仔細了,這很重要

介紹bean之前,說下ioc和context上下文(可以理解爲一個宿主環境)

ioc是Inversion of Control的簡稱,行內話叫控制反轉,早期開發都是需要對象,自己new出來一個,可有了ioc後,我們不需要

自己new對象了,讓spring ioc容器負責對象的創建和管理。一句話概括ioc的作用顛倒了對象的依賴關係,ioc容器管理對象。

儘量搞明白bean,ioc,context,對以後學spring生態很重要。

 

Spring bean 分兩種,一種普通bean,一種是工廠型的bean,但處理類型很多

一, 普通bean(以xml配置爲例,現在改用註解的人越來越多了)

準備好原材料

spring-bean.xml文件(以演示爲例)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
	<bean id="user" class="spring.model.User">
		<property name="id" value="1"/>
		<property name="name" value="dongguangming"/>
		<property name="age" value="99"/>
	</bean>
    
</beans>

      User.java

public class User {

	private int id;
	private String name;
	private int age;
   //set,get略
}

測試類

/**
 * 
 * @author dgm
 * @describe "xml bean"
 * @date 2020年4月16日
 */
public class XMLConfigurationBeanApp {
	public static void main(String[] args) {
		/*DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
		
		reader.loadBeanDefinitions("conf/spring-bean.xml");*/
		 ApplicationContext applicationContext = 
	                new ClassPathXmlApplicationContext("conf/spring-bean.xml");
		User user1 = applicationContext.getBean("user", User.class);
		User user2 = (User) applicationContext.getBean("user");
		System.out.println(user1);
		System.out.println(user2);
		System.out.println(user1==user2);

		//由於是個普通的bean,故出現異常,生成環境就不需要這樣寫了,我是測試兩種不同類型的bean
		System.out.println(applicationContext.getBean("&user"));
	}
}

 輸出結果

解析初始化過程,就從這行代碼

 ApplicationContext applicationContext = 
	                new ClassPathXmlApplicationContext("spring-bean.xml");

說起,看看spring做了多少事

 三大階段:bean解析,bean實例化,bean初始化,銷燬

1. bean解析定義註冊階段

早期開發人員都知道,配置文件以xml文件(現在人都喜歡註解解析了)居多,要把xml文件內容解析成java對應的類,簡稱dom解析,如

spring也是如此,一開始進行大量的xml文件解析工作,和java對應的類映射好

文件路徑org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException


/**
	 * Actually load bean definitions from the specified XML file.
	 * @param inputSource the SAX InputSource to read from
	 * @param resource the resource descriptor for the XML file
	 * @return the number of bean definitions found
	 * @throws BeanDefinitionStoreException in case of loading or parsing errors
	 * @see #doLoadDocument
	 * @see #registerBeanDefinitions
	 */
	protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
            //xml文檔解析
			Document doc = doLoadDocument(inputSource, resource);
            //調用註冊bean定義
			return registerBeanDefinitions(doc, resource);
		}
}

文件路徑org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
        //調用bean註冊
		documentReader.registerBeanDefinitions(doc, 
createReaderContext(resource));

		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

。。。。。。嵌套很多

文件路徑org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

/**
	 * Process the given bean element, parsing the bean definition
	 * and registering it with the registry.
	 */
	protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
                //調用註冊工具註冊
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

文件路徑org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException


@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;

		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		if (oldBeanDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"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 (!beanDefinition.equals(oldBeanDefinition)) {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
            //終於測測成功了,一種數據結構
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
                   //同上
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

 這只是一個bean定義(開發過程時有很多很多個Bean定義註冊),很重要做那麼多工作就是爲了組裝成這種數據結構:this.beanDefinitionMap.put(beanName, beanDefinition);它是這麼定義的:

/** Map of bean definition objects, keyed by bean name */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

 beanDefinition的部分屬性,把它當然一種組裝數據的結構就行

 2. Bean實例化和初始化階段

調用時

ClassPathXmlApplicationContext(AbstractApplicationContext).finishBeanFactoryInitialization(ConfigurableListableBeanFactory) line: 861	

{
//部分代碼
// Register a default embedded value resolver if no bean post-processor
		// (such as a PropertyPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
				@Override
				public String resolveStringValue(String strVal) {
					return getEnvironment().resolvePlaceholders(strVal);
				}
			});
		}

// Instantiate all remaining (non-lazy-init) singletons.
//這裏面東西可多了去了
		beanFactory.preInstantiateSingletons();
}

 preInstantiateSingletons核心代碼:

@Override
	public void preInstantiateSingletons() throws BeansException {


		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// 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)) {
                    //工廠型bean(系統自帶很多,當然也可以自己寫),實現FactoryBean接口或繼承AbstractFactoryBean
					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 {
                    //普通bean,人爲實現,沒有實現FactoryBean接口或沒有繼承AbstractFactoryBean
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged(new PrivilegedAction<Object>() {
						@Override
						public Object run() {
							smartSingleton.afterSingletonsInstantiated();
							return null;
						}
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

 

0:DefaultListableBeanFactory(AbstractBeanFactory).getBean(String)

1 DefaultListableBeanFactory(AbstractBeanFactory).doGetBean(String, Class<T>, Object[], boolean) line: 303    
2 DefaultListableBeanFactory(DefaultSingletonBeanRegistry).getSingleton(String) line: 231    ,第一次getSingleton
3 Object org.springframework.beans.factory.support.AbstractBeanFactory.createBean(String beanName, RootBeanDefinition mbd, Object[] args) 

要分叉了:

4. org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)

判斷是否有InstantiationAwareBeanPostProcessor,applyBeanPostProcessorsBeforeInstantiation()>postProcessBeforeInstantiation(),

applyBeanPostProcessorsAfterInitialization()>postProcessAfterInitialization().

返回代理對象的機會,一旦返回,就沒有下面的事了,aop代理由此可生

如果return ,直接跳到10階段
5 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(String beanName, 4 RootBeanDefinition mbd, Object[] args)  很重要
6 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args), 實例化完成,詳細請繼續看源碼,注意實例化方式不止一種:構造器,工廠方法,

cglid代理
7 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(beanName, mbd, instanceWrapper),詳細請繼續看源碼,下面是部分

if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}

			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}

此階段也有機會產生分叉,特別是實現了InstantiationAwareBeanPostProcessor,提前返回,不再進行後續的autowireByName,autowireByType和屬性賦值操作,但並不影響初始化操作
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(String beanName, Object bean, RootBeanDefinition mbd),初始化完成

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;
				}
			}, getAccessControlContext());
		}
		else {
            //實現了後綴名Aware接口的調用在這個階段,通知感應
            //BeanNameAware
            //BeanClassLoaderAware
            //BeanFactoryAware
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
            //實現BeanPostProcessor接口
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
            //調用初始化方法,判斷是否實現了InitializingBean,方法名afterPropertiesSet(),自定義初始化方法也在這裏
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
             //實現BeanPostProcessor接口
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

10 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(String beanName, ObjectFactory<?> singletonFactory),第二次getSingleton,但實現方法不一樣

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry


/** Cache of singleton objects: bean name --> bean instance */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name --> ObjectFactory */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name --> bean instance */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

注意篇幅有限: 列了一些核心方法,其實還有很多,由於代碼量超超多,就不貼了
 

工廠型bean

該Bean實現了FactoryBean接口

public class UserFactoryBean<User> implements FactoryBean<User> {

	private User user;
	
	
	/**
	 * @return the user
	 */
	public User getUser() {
		return user;
	}

	
	/**
	 * @param user the user to set
	 */
	public void setUser(User user) {
		this.user = user;
	}

	
	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.FactoryBean#getObjectType()
	 */
	@Override
	public Class<?> getObjectType() {
		return user.getClass();
	}


	/* (non-Javadoc)
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	@Override
	public User getObject() throws Exception {
		// TODO Auto-generated method stub
		return user;
	}

}

它和上面沒有實現FactoryBean接口的處理方式不太一樣,大體上相同不再贅述

/**
	 * Obtain an object to expose from the given FactoryBean.
	 * @param factory the FactoryBean instance
	 * @param beanName the name of the bean
	 * @param shouldPostProcess whether the bean is subject to post-processing
	 * @return the object obtained from the FactoryBean
	 * @throws BeanCreationException if FactoryBean object creation failed
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		if (factory.isSingleton() && containsSingleton(beanName)) {
			synchronized (getSingletonMutex()) {
				Object object = this.factoryBeanObjectCache.get(beanName);
				if (object == null) {
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (object != null && shouldPostProcess) {
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
						}
						this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
					}
				}
				return (object != NULL_OBJECT ? object : null);
			}
		}
		else {
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (object != null && shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

順序圖:

3.  bean銷燬

三種體現:

3.1  和初始化InitializingBean對應的DisposableBean接口,

3.2  自定義方法,destroy-method="destroyXML"

3.3  和@PostConstruct對應的 @PreDestroy

銷燬順序如圖

代碼就不舉例了。

 

總結:其實你可以new User(6,"dongguangmming",99),但和spring沒關係,Spring很強大,各個階段都有機會改造參與bean的過程,組合度也很高,****BeanDefinitionRegistryPostProcessor,***BeanPostProcessor,***BeanFactory,****BeanFactoryPostProcessor

記住Spring bean:解析註冊,實例化,初始化,銷燬,才能做擴展性開發或集成第三方組件(比如mybatis,dubbo,email,zk,redis等)到spring的生態圈裏

 

參考:

0 Spring 框架簡介 https://www.ibm.com/developerworks/cn/java/wa-spring1/

1. spring bean是什麼 https://www.awaimai.com/2596.html

2  what-in-the-world-are-spring-beans https://stackoverflow.com/questions/17193365/what-in-the-world-are-spring-beans

3. Spring Bean Lifecycle https://www.benchresources.net/spring-bean-lifecycle/

4. Detailed tutorial on Redis caching in the SpringBoot series  https://laptrinhx.com/detailed-tutorial-on-redis-caching-in-the-springboot-series-3352915639/

5. Spring Bean creation process http://www.programmersought.com/article/55942589567/

6. Inversion of Control Containers and the Dependency Injection pattern https://martinfowler.com/articles/injection.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章