Spring Bean的运行实现源码解析

Spring Bean的运行(获取、创建)实现

 

1.通过BeanFactory获取bean流程:

代码如下:

Resource resource = new ClassPathResource("bean.xml");
BeanFactory factory = new XmlBeanFactory(resource);
IAccountService yunyun  = (IAccountService)factory.getBean("zhu");

打断点在:IAccountService yunyun  = (IAccountService)factory.getBean("zhu");

逐步Step into可得:

Step one

Spring Bean的运行实现源码解析_第1张图片

 

Step two:

Spring Bean的运行实现源码解析_第2张图片

这里的deGetBean()方法执行流程类似于下面的 通过ApplicationContext获取bean的流程 中doGetBean()方法的执行流程,故不再赘述。

 

2.通过ApplicationContext获取bean的流程:

代码如下:

//1.获取核心容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//2.根据id获取Bean对象
IAccountService yunyun  = (IAccountService)ac.getBean("zhu");

 

打断点在:  IAccountService yunyun  = (IAccountService)ac.getBean("zhu");

Step into后可看到源码,

Spring Bean的运行实现源码解析_第3张图片

上图中Return this.getBeanFactory().getBean(name);时,step into,经过若干步后会调用下图的代码

Spring Bean的运行实现源码解析_第4张图片

 

上图中的doGetBean()方法会调用

Spring Bean的运行实现源码解析_第5张图片

 

下面是上图中的doGetbean方法的源码解析:

Spring Bean的运行实现源码解析_第6张图片

Spring Bean的运行实现源码解析_第7张图片

Spring Bean的运行实现源码解析_第8张图片

 

书中所给的代码与我看到的源码有部分出入,不过关系不大,不影响整体逻辑性

上图中代码的划黑线的部分代码如下:

Spring Bean的运行实现源码解析_第9张图片

Spring Bean的运行实现源码解析_第10张图片

上图中黑线部分源码解析如下:

Spring Bean的运行实现源码解析_第11张图片

Spring Bean的运行实现源码解析_第12张图片

上图是getObjectForBeanInstance()方法的源码,通过源码可知,

如果当前 Bean的类型是FactoryBean,则在getBean时不是直接返回 当前 Bean实例,而是先获取Bean实例,然后调用其工厂方法获取Bean 实例。

最后的getObjectFromFactoryBean方法的

源码中,

执行了//获取bean

Object object = doGetObjectFromFactoryBean(factory, beanName);

doGetObjectFromFactoryBean()源码如下:

private Object doGetObjectFromFactoryBean(final FactoryBean factory, final String beanName)
			throws BeanCreationException {

		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				//真正的获取bean实例对象的代码
				//里面使用动态代理Proxy.newProxyInstance来进行bean实例对象的获取
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

其中:

//真正的获取bean实例对象的代码

//里面使用动态代理Proxy.newProxyInstance来进行bean实例对象的获取

                            object = factory.getObject();

红色代码部分,执行了factorybean的getobject()方法。

总结:

getBean()方法整体流程如下:

Spring Bean的运行实现源码解析_第13张图片

 

下面是getbean过程中,AbstractAutowireCapableBeanFactory中的doCreateBean()方法流程:

Spring Bean的运行实现源码解析_第14张图片

 

 

注:

Bean的作用范围(Scope)决定了这个Bean的生命周期, Spring对Scope的扩展和订制是Spring Bean模块对Web环境更复杂的Bean 生命周期管理的支持。 Spring Bean的生命周期主要如下。

◎ 单例(Singleton)的生命周期和 Spring 上下文的生命周期一 致,自始至终只被Sping创建一次。

◎ 多例(Prototype)的生命周期在事件级别,每触发一次 getBean,调用方获取的实例就是新的。

◎ Request的生命周期在HTTP请求级别,在每次Web HTTP请求中 都被创建一次。

◎ Session的生命周期在HTTP Session级别,在每个HTTP Session中 都被创建一次。

◎ Global Session的生命周期类似于Session的生命周期,但仅在基 于Portlet的Web应用中有意义。PorletSession继承自HttpSession,使用目 的和HttpSession一致。

◎ Application的生命周期与整个Web应用的生命周期一致。

 

注:本文基于 互联网轻量级SSM框架解密:Spring、Spring MVC、MyBatis源码深度剖析  一书创作。

 

你可能感兴趣的:(SSM源码,spring,java,bean)