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:
Step two:
这里的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后可看到源码,
上图中Return this.getBeanFactory().getBean(name);时,step into,经过若干步后会调用下图的代码
上图中的doGetBean()方法会调用
下面是上图中的doGetbean方法的源码解析:
书中所给的代码与我看到的源码有部分出入,不过关系不大,不影响整体逻辑性
上图中代码的划黑线的部分代码如下:
上图中黑线部分源码解析如下:
上图是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<Object>) 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()方法整体流程如下:
下面是getbean过程中,AbstractAutowireCapableBeanFactory中的doCreateBean()方法流程:
注:
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源码深度剖析 一书创作。