IOC容器的基接口提供了三个获取Bean的方法:
Object getBean(String name) throws BeansException;
Object getBean(String name, Class requiredType) throws BeansException;
Object getBean(String name, Object[] args) throws BeansException;
顺着XmlBeanFactory的继承结构向上找,会在AbstractBeanFactory类中找到这三个类的实现:
public Object getBean(String name) throws BeansException {
return getBean(name, null, null);
}
public Object getBean(String name, Class requiredType) throws BeansException {
return getBean(name, requiredType, null);
}
public Object getBean(String name, Object[] args) throws BeansException {
return getBean(name, null, args);
}
这三个#getBean()方法都调用了同一个#getBean(String, Class, Object[])方法,它的实现如下:
public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
这样,处理过程就到了#doGetBean()方法了。
protected Object doGetBean(final String name, final Class requiredType, final Object[] args,
boolean typeCheckOnly) throws BeansException {
// 处理"&"前缀和别名
final String beanName = transformedBeanName(name);
Object bean = null;
// 获得原始的单例对象
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {// 如果已经创建了这个实例
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 对sharedInstance进行一些判断(如FactoryBean等),来获得最终的Bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {// 如果还没有创建
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查在父BeanFactory中有没有这个Bean的定义
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
} else {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 标记Bean已经创建,其实是在一个名字是alreadyCreated的Set里加入beanName
markBeanAsCreated(beanName);
}
// 返回BeanDefinition,里边包括了xml中定义的bean的信息
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 检查Bean的dependsOn,如果有的话就要先实例化它所依赖的Bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (int i = 0; i < dependsOn.length; i++) {
String dependsOnBean = dependsOn[i];
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
if (mbd.isSingleton()) {
// 如果Bean是单例的,创建一个单例
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 销毁单例
destroySingleton(beanName);
throw ex;
}
}
});
// 根据单例生成Bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// 创建prototype的实例,每次都创建一个新的实例
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 得到scope,为RequestScope,SessionScope中的一个
String scopeName = mbd.getScope();
final Scope scope = (Scope) this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException ex) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex);
}
}
}
// 检查Bean的类是否正确
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return bean;
}
这个方法的实现包括了几个需要进一步查看的点。首先,是单例对象的获取,就是#getSingleton(String)这个方法
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从已经创建的单例对象map中获取实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
synchronized (this.singletonObjects) {
// 从已经创建的early单例对象map中获取实例
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 获得单例工厂
ObjectFactory singletonFactory = (ObjectFactory) this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 在earlySingletonObjects这个Map中"注册"上这个Bean,下次相同的Bean就可以直接获取了
this.earlySingletonObjects.put(beanName, singletonObject);
// 在singletonFactories移除相关的记录
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
这个方法中涉及到了3个Map,singletonObjects,earlySingletonObjects和singletonFactories。另外还有一个ObjectFactory的实例用来生成单例,接下来的介绍中还会出现这些对象的,先做一个提醒。
回到#doGetBean()方法,在通过#getSingleton(String)方法获得了单例后,程序出现了两个分支,其中之一是sharedInstance不为null,就是说之前的操作中已经实例化了一个与此beanName相关的实例,另外还要当args为null(args不为null一定是prototype的Bean)时,那么就可以准备获取最终的Bean实例了,具体是通过这个getObjectForBeanInstance(Object, String, String, RootBeanDefinition)方法,它的源代码如下:
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName,
RootBeanDefinition mbd) {
// 如果name以"&"开头,并且beanInstance不是FactoryBean的情况下,抛出异常
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
// 分两种情况
// 1. beanInstance不是FactoryBean,name不是以"&"开头,此时返回bean
// 2. beanInstance是FactoryBean,name是以"&"开头,此时返回FactoryBean
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
// 最后一种情况是name不是以"&"开头,并且beanInstance是FactoryBean的情况
// 此时要调用FactoryBean来构造一个Bean了
Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
FactoryBean factory = (FactoryBean) beanInstance;
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
// 调用FactoryBean的#getObject()来构建bean
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
执行完这个方法后就可以返回Bean的实例给客户端了。
好,再次回到#doGetBean()方法,进入到另外一个分支,就是IOC容器之前还没有实例化sharedInstance的情况,这是就要新建一个了。在具体的Bean实例生成过程中,按照Scope出现了3个不同的实现方式,分别为singleton,prototype以及request和session。
对于scope为singleton的情况,首先获取一个bean的单例,然后根据单例来获取最终的Bean实例。
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 销毁单例
destroySingleton(beanName);
throw ex;
}
}
});
// 根据单例生成Bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
这里的bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);这句方法调用之前已经讲过了,需要重点了解的是那个单例的获取。
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 尝试直接获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while the singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet();
}
try {
// 通过ObjectFactory来获取实例
singletonObject = singletonFactory.getObject();
} catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Iterator it = this.suppressedExceptions.iterator(); it.hasNext();) {
ex.addRelatedCause((Exception) it.next());
}
}
throw ex;
} finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
afterSingletonCreation(beanName);
}
//向singletonObjects这个Map注册刚生成的实例,下次可以直接从Map中获取
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
这个方法的重点是知道了Bean单例的创建过程是通过ObjectFactory的#getObject()方法来完成的,另外,在方法的最后会向Map中注册新成生的实例。与#doGetBean()方法前面的处理过程形成呼应了。
下面还是来看看这个#getObject()方法,这个是通过匿名类来实现的:
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
} catch (BeansException ex) {
// 销毁单例
destroySingleton(beanName);
throw ex;
}
}
});
在#getObject()内调用了#createBean()方法,而这个方法在AbstractBeanFactory中是abstract的,需要子类去实现,我们可以来看看子类是怎么实现的。
在XmlFactoryBean的一个父类,并且是AbstractBeanFactory的一个子类AbstractAutowireCapableBeanFactory中就有一个这样的定义:
protected Object createBean(final String beanName, final RootBeanDefinition mbd,
final Object[] args) throws BeanCreationException {
AccessControlContext acc = AccessController.getContext();
return AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
resolveBeanClass(mbd, beanName);
try {
// 方法重写功能
mbd.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"Validation of method overrides failed", ex);
}
try {
// 创建一个Bean的proxy
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 创建一个Bean的实例
Object beanInstance = doCreateBean(beanName, mbd, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
}, acc);
}
这里,#resolveBeforeInstantiation()是用于处理继承了InstantiationAwareBeanPostProcessor接口的类的回调,重要的是#doCreateBean()方法,但是此方法的流程比较长,下一节接着说。
分享到:
相关推荐
Spring.Demo项目很可能是包含一个简单的Spring.NET应用示例,可能包括了XML配置文件、服务接口和实现类、以及如何使用IoC容器来获取和使用这些对象的代码。通过这个示例,你可以更直观地了解如何在实际项目中运用...
在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...
注解是Java语言提供的一种元数据机制,允许我们在源代码中嵌入信息,这些信息可以被编译器或者运行时环境解析和使用。Spring框架充分利用了这一特性,提供了一系列注解来简化配置,使得我们可以避免使用XML配置文件...
Spring源代码解析(一):IOC容器 Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源...
Spring源代码解析1:IOC容器.doc Spring源代码解析2:IoC容器在Web容器中的启动.doc Spring源代码解析3:Spring JDBC .doc Spring源代码解析4:Spring MVC .doc Spring源代码解析5:Spring AOP获取Proxy .doc Spring...
IoC容器是Spring框架的心脏,它负责管理对象的生命周期和依赖关系,使得开发者能够实现松耦合和高可测试性的应用程序。 首先,我们来理解什么是IoC。IoC,也被称为依赖注入(Dependency Injection),是一种设计...
Spring源代码解析1:IOC容器;Spring源代码解析2:IoC容器在Web容器中的启动;Spring源代码解析3:Spring JDBC ; Spring源代码解析4:Spring MVC ;Spring源代码解析5:Spring AOP获取Proxy;Spring源代码解析6:...
当我们在Web环境中运行Spring应用时,IoC容器需要在Web容器(如Tomcat、Jetty等)中启动并运行。这个过程涉及到一系列的初始化步骤,确保Spring能够正确地与Web容器集成。 首先,`WebApplicationContext`是`...
Spring支持多种持久化技术,如JDBC、Hibernate、MyBatis等,可以利用IoC容器管理这些DAO对象,使它们能够依赖于事务管理、数据源等服务。 **工厂模式** 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳...
### Spring IoC容器部署实现详解 #### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理...
spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和Classpath扫描 spring-expression:表达式语句 切面编程: spring-aop:面向切面编程,...
通过阅读和学习这些源码,开发者可以了解到Spring如何实现IoC容器、AOP代理、事件机制、任务调度等多个关键功能。同时,这也有助于开发者更好地理解和使用Spring提供的API,以及在实际项目中如何定制和扩展Spring。 ...
3. `TestIoC.java`:这是一个关于IoC容器的测试类,它可能使用Spring的ApplicationContext接口来加载bean.xml配置,然后通过容器获取并测试bean实例。 4. `ServiceBean.java`:这可能是一个通用的服务bean,用于...
例如,`StrutsActionProxy`类是如何拦截Struts的请求,然后通过Spring的IoC容器查找并调用对应的bean方法。同时,源代码中还展示了如何将Struts的配置信息与Spring的bean定义相结合,实现配置的统一管理和重用。 ...
这里提到的是一组完整的Spring库,包括`spring-core`、`spring-context`、`spring-webmvc`、`spring-web`、`spring-beans`、`spring-test`、`spring-jdbc`、`spring-orm`、`spring-aop`和`spring-tx`,它们都是3.2.0...
2. **Web环境下的IOC容器启动**:"spring源代码解析(二):IOC容器在web中启动.doc"涵盖了在Web应用中初始化Spring容器的过程,包括ApplicationContext的创建、DispatcherServlet的配置以及如何在Web环境中注入bean...
通过阅读并分析这些源代码,开发者可以更深入地理解Spring框架的工作机制,学习如何有效地使用其特性来提高代码的可维护性和可扩展性。每个章节都会提供实际的示例,帮助开发者将理论知识转化为实践技能。对于想要...
Spring IoC容器通过解析XML配置文件或使用注解来识别对象及其依赖关系,并在运行时自动装配这些对象,这就是依赖注入。 在Spring中,注解配置是取代传统XML配置的一种方式,它使得代码更加简洁、易读。例如,我们...