Spring是知道很久了,一直断断续续在看,不过用到它的机会不是很多,于是想阅读一下Spring的源代码来更深入的了解下这个框架(源代码的版本是2.5.6)。首先,当然是从Spring的IOC容器开始了,最基本的IOC容器就是org.springframework.beans.factory.BeanFactory了,这个接口定义了一个基本的IOC容器应该具有的行为,其源代码如下所示:
public interface BeanFactory {
/** 通过在bean的名字前加上&可以返回生成Bean的FactoryBean本身 */
String FACTORY_BEAN_PREFIX = "&";
/** 根据名字返回Bean */
Object getBean(String name) throws BeansException;
/** 根据名字和类型返回Bean */
Object getBean(String name, Class requiredType) throws BeansException;
/** 用于使用静态方法工厂创建prototype的bean,args是给工厂方法的参数 */
Object getBean(String name, Object[] args) throws BeansException;
/** 查询IOC容器中是否有特定名字的Bean */
boolean containsBean(String name);
/** 判断Bean是不是单例的 */
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/** 判断Bean是不是原型的 */
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/** 判断名字为name的Bean的类型是否是targetType */
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
/** 返回Bean的类型 */
Class getType(String name) throws NoSuchBeanDefinitionException;
/** 判断Bean的所有别名,如果使用别名查询的,那么Bean的原始名字也会返回的 */
String[] getAliases(String name);
}
BeanFactory是一切IOC容器类的基接口,它定义了IOC容器的基本行为,下面来看几个具体的实现类,首先从XmlBeanFactory开始。
public class XmlBeanFactory extends DefaultListableBeanFactory {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
这个类的构造函数说明了配置文件的载入过程,就是通过XmlBeanDefinitionReader的#loadBeanDefinitions()方法来载入的,源代码如下:
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
它又进一步调用了#loadBeanDefinitions(EncodedResource)这个方法,它的源代码如下。
public int loadBeanDefinitions(EncodedResource encodedResource)
throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set currentResources = (Set) this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
// 如果Set中已经包含了这个资源,那么就不要重复载入
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException("Detected recursive loading of "
+ encodedResource + " - check your import definitions!");
}
try {
// 构建一个解析XML使用的InputStream对象
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 实做Bean定义的载入
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
inputStream.close();
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException("IOException parsing XML document from "
+ encodedResource.getResource(), ex);
} finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.set(null);
}
}
}
这样,经过了一些列的处理,最后来到了实做载入的#doLoadBeanDefinitions()方法。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
int validationMode = getValidationModeForResource(resource);
// 通过InputSource来载入XML到一个Document对象
Document doc = this.documentLoader.loadDocument(inputSource, getEntityResolver(),
this.errorHandler, validationMode, isNamespaceAware());
// 注册Bean的定义
return registerBeanDefinitions(doc, resource);
} catch (BeanDefinitionStoreException ex) {
throw ex;
} catch (SAXParseException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line "
+ ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
} catch (SAXException ex) {
throw new XmlBeanDefinitionStoreException(resource.getDescription(),
"XML document from " + resource + " is invalid", ex);
} catch (ParserConfigurationException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Parser configuration exception parsing XML from " + resource, ex);
} catch (IOException ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"IOException parsing XML document from " + resource, ex);
} catch (Throwable ex) {
throw new BeanDefinitionStoreException(resource.getDescription(),
"Unexpected exception parsing XML document from " + resource, ex);
}
}
下面首先来看一下这个Document的获取过程,这里documentLoader是一个org.springframework.beans.factory.xml.DefaultDocumentLoader类的对象,通过它的#loadDocument()方法可以获得一个Document对象,这个过程先不去仔细看,主要来看一下这个#registerBeanDefinitions()方法。
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 支持老的XmlBeanDefinitionParser
if (this.parserClass != null) {
XmlBeanDefinitionParser parser = (XmlBeanDefinitionParser) BeanUtils
.instantiateClass(this.parserClass);
return parser.registerBeanDefinitions(this, doc, resource);
}
// 使用BeanDefinitionDocumentReader来载入
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 已经注册的Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
// 注册Bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
这里XmlBeanDefinitionParser的处理就不仔细看了,因为是Spring为了兼容老的实现而保留的,下边主要来看一下使用BeanDefinitionDocumentReader的处理过程。
首先就应该是BeanDefinitionDocumentReader的构造,就是#createBeanDefinitionDocumentReader()方法
protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() {
return (BeanDefinitionDocumentReader) BeanUtils.instantiateClass(this.documentReaderClass);
}
这里的documentReaderClass这个变量的值为DefaultBeanDefinitionDocumentReader.class,也就是org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader,也就是BeanDefinitionDocumentReader的实现类。
下面来看看它的#registerBeanDefinitions()方法。
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
// 根元素
Element root = doc.getDocumentElement();
// 这个类很重要,主要是委托给它来实现解析
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
// 如果想自己实现Bean的注册过程,可以继承DefaultBeanDefinitionDocumentReader,
// 然后覆盖#preProcessXml()和#postProcessXml()来完成更多的个性化实现。
// 处理XML前,默认无行为
preProcessXml(root);
// 解析Bean的定义
parseBeanDefinitions(root, delegate);
// 处理XML后,默认无行为
postProcessXml(root);
}
这个方法有两个部分需要考虑下,一个是BeanDefinitionParserDelegate实例的构建,另外一个是#parseBeanDefinitions()方法。
首先来看一下BeanDefinitionParserDelegate的构建
protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) {
BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
delegate.initDefaults(root);
return delegate;
}
这里调用了BeanDefinitionParserDelegate的#initDefaults()方法来初始化,并把document的root元素作为参数传递了进去。这个方法主要是对一些全局属性的初始化,可以看看它的源代码:
public void initDefaults(Element root) {
DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition();
// default-lazy-init -> 默认的延迟加载
defaults.setLazyInit(root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE));
// default-merge -> 对集合类的默认merge处理
defaults.setMerge(root.getAttribute(DEFAULT_MERGE_ATTRIBUTE));
// default-autowire -> 默认的自动装配
defaults.setAutowire(root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE));
// default-dependency-check -> 默认的依赖检测
defaults.setDependencyCheck(root.getAttribute(DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE));
// default-autowire-candidates -> 查找自动装配的Bean的样式
if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) {
defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE));
}
// default-init-method -> 默认初始化方法
if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
}
// default-destroy-method -> 模式销毁方法
if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
}
defaults.setSource(this.readerContext.extractSource(root));
this.defaults = defaults;
this.readerContext.fireDefaultsRegistered(defaults);
}
这个方法提供了针对根标签<beans>的属性(xml定义的bean的一些默认行为)的载入。在这里会看到很多spring配置文件中出现过的身影。
看过了BeanDefinitionParserDelegate之后,下面就来看看#parseBeanDefinitions()方法的定义吧:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
String namespaceUri = ele.getNamespaceURI();
if (delegate.isDefaultNamespace(namespaceUri)) {
// 解析默认的标签
parseDefaultElement(ele, delegate);
} else {
// 解析不是在默认命名空间的
delegate.parseCustomElement(ele);
}
}
}
} else {
// 解析不是在默认命名空间的
delegate.parseCustomElement(root);
}
}
下面是#parseDefaultElement()的定义:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// <import>的处理
if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// <alias>的处理
else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// <bean>的处理
else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
}
#parseDefaultElement()包含了<beans>标签的所有子标签的处理。
剩下的内容下次再说。:)
分享到:
相关推荐
Spring.Demo项目很可能是包含一个简单的Spring.NET应用示例,可能包括了XML配置文件、服务接口和实现类、以及如何使用IoC容器来获取和使用这些对象的代码。通过这个示例,你可以更直观地了解如何在实际项目中运用...
在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...
### Spring源码分析_Spring_IOC:深入理解Spring的IOC容器机制 #### 基本概念与核心作用 在探讨Spring框架的核心组件之一——IOC(Inversion of Control,控制反转)容器之前,首先需要理解它在Spring框架中的角色...
注解是Java语言提供的一种元数据机制,允许我们在源代码中嵌入信息,这些信息可以被编译器或者运行时环境解析和使用。Spring框架充分利用了这一特性,提供了一系列注解来简化配置,使得我们可以避免使用XML配置文件...
《Spring IOC容器实现分析》 在Java开发领域,Spring框架无疑是使用最为广泛的轻量级框架之一,其中的核心组件就是IOC(Inversion of Control)容器。本文将深入剖析Spring的IOC容器,理解其工作原理和重要功能,以...
这里提到的是一组完整的Spring库,包括`spring-core`、`spring-context`、`spring-webmvc`、`spring-web`、`spring-beans`、`spring-test`、`spring-jdbc`、`spring-orm`、`spring-aop`和`spring-tx`,它们都是3.2.0...
1. **spring-context-3.1.2.RELEASE.jar**:提供Spring的IoC(Inversion of Control)容器和AOP(Aspect Oriented Programming)支持,这是Spring框架的基础,为Spring Security提供了配置和事件处理能力。...
2. **Spring容器**:Spring的核心是IoC容器,如BeanFactory和ApplicationContext,它们负责读取配置,实例化、配置及管理Bean。 3. **Bean定义**:如何在XML或Java配置中定义Bean,包括其类名、初始化方法、属性...
IoC容器是Spring框架的心脏,它负责管理对象的生命周期和依赖关系,使得开发者能够实现松耦合和高可测试性的应用程序。 首先,我们来理解什么是IoC。IoC,也被称为依赖注入(Dependency Injection),是一种设计...
例如,Spring的事件驱动模型、AOP的实现原理、以及IoC容器的内部工作流程等。此外,源码还展示了Spring如何与其他技术(如JDBC、JMS、EJB等)无缝集成,以及如何利用注解简化配置。 通过阅读和分析"spring-...
spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和Classpath扫描 spring-expression:表达式语句 切面编程: spring-aop:面向切面编程,...
### Spring的IoC容器初始化源码解析 #### 一、Spring框架的核心——IoC容器 Spring框架是一个开源的轻量级Java开发框架,其核心功能是IoC(Inversion of Control,控制反转)容器和AOP(Aspect Oriented ...
Spring支持多种持久化技术,如JDBC、Hibernate、MyBatis等,可以利用IoC容器管理这些DAO对象,使它们能够依赖于事务管理、数据源等服务。 **工厂模式** 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳...
IOC容器是 Spring 框架的核心组件之一,它提供了一个统一的方式来管理应用程序中的对象。IOC 容器的主要功能是将对象的创建、管理和依赖关系解耦,使得应用程序更加灵活、可维护和可扩展。 在 Spring 中,IOC 容器...
3、源码分析-IOC容器的初始化 4、源码分析-IOC容器的依赖注入 5、源码分析-IOC容器的高级特性 三阶段 Spring AOP的涉及原理及具体实践 SpringJDBC的涉及原理及二次开发 SpringMVC框架设计原理及手写实现 四阶段 ...
首先,源码分析从`spring-framework-5.1.4.RELEASE-dist.zip`开始,这是Spring框架的基础组件包,包含了所有核心模块的类库和配置文件。主要模块有Core Container(核心容器)、Data Access/Integration(数据访问与...
#### 一、Spring IoC容器概述 Spring框架的核心特性之一就是Inversion of Control(IoC),也被称为Dependency Injection(DI)。IoC容器是Spring框架的重要组成部分,它负责管理对象的生命周期、配置和装配过程。...
1. **IoC(Inversion of Control)容器**:Spring的核心在于IoC容器,它负责管理对象的生命周期和依赖关系。在源码中,`BeanFactory`是IoC的基础接口,而`ApplicationContext`则提供了更高级的应用上下文功能。通过...
IoC容器管理对象的生命周期和依赖关系,而AOP则实现了关注点分离,提高了代码的可维护性。在源码中,我们可以看到`org.springframework.beans`和`org.springframework.context`包是如何实现这些功能的。 `spring-...
Spring的IoC(Inversion of Control)容器和AOP(Aspect-Oriented Programming)支持在5.3.2中得到加强,包括对Java配置的优化,以及对注解的更精细控制。此外,还增强了Bean生命周期管理,如条件化 Bean 的创建和...