一个Spring Bean从无到有的过程

Posted 董广明

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个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;
		}
技术图片


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

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

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

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

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

以上是关于一个Spring Bean从无到有的过程的主要内容,如果未能解决你的问题,请参考以下文章

从无状态 Bean 中获取 JDBC 连接对象

spring bean的装载过程简略赏析

照虎画猫写自己的Spring——依赖注入

当没有代码的时候,Spring之Bean实例化过程是什么样子的呢?

Spring源码分析非懒加载的Bean实例化过程(下篇)

死磕 Spring----- IOC 之从单例缓存中获取单例 bean