- 浏览: 243702 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
feifei435:
不错的文章,但是有一点忘了提,创建了新的sessionid后, ...
Tomcat的Session管理(一) - Session的生成 -
yangcheng33:
博主你为什么这么棒!!!
Tomcat的Session管理(一) - Session的生成 -
u010323779:
哈哈,非常不错,昨天看了一天源代码,不知从何入手,现在看来您的 ...
Tomcat的Session管理(二) - Session后台处理 -
hdwmp123:
...
Tomcat请求处理(一) -- 服务器端口监听 -
tinguo002:
...
Tomcat的Session管理(一) - Session的生成
上一篇文章讲到了对<import>,<alias>,<bean>标签处理的方法org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseDefaultElement()。
可以来简单的看一下各个子标签的处理,首先是<import>
这个就是<import>的大致处理过程了,如果有兴趣可以简单的看一下占位符的处理(org.springframework.util.SystemPropertyUtils#resolvePlaceholders()),我把注释后的代码也一并贴上。
第二个是<alias>的处理
这里还存在一个疑点,就是注册alias的过程,这里详细写出来的话会比较长,暂时就不详细写查找getRegistry()方法返回是哪个类的实例的过程了。
直接给出结论吧,这里返回的BeanDefinitionRegistry接口的实现就是XmlBeanFactory类本身,而这个registerAlias()就要顺着继承树向上查找了,直到org.springframework.core.SimpleAliasRegistry类为止,这个类实现了registerAlias()方法。
至此,我们知道了alias的相关信息是放在SimpleAliasRegistry的一个成员变量aliasMap中存储的。
看完了<alias>标签后,最后来看一下最重要的<bean>标签的处理,对应的方法是#processBeanDefinition()
这里有两个重要的方法需要仔细研究,一个是BeanDefinitionParserDelegate的#parseBeanDefinitionElement(),另外一个是BeanDefinitionReaderUtils的#registerBeanDefinition。首先来看第一个
这个方法对<bean>标签进行了分析,其中有一个AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);这条语句是对<bean>标签的属性进行分析,可以来看一下它的源代码:
这里边包括了对<bean>标签下的所有属性和子标签的解析,很多细节就不详细的说明了,主要看看解析<bean>标签属性的函数吧,就是这个#parseBeanDefinitionAttributes()方法。
这里边包含了所有熟悉的属性定义。看完了标签的解析,下面就要来看一下前面提到的另外的bean的注册过程了,也就是BeanDefinitionReaderUtils的#registerBeanDefinition方法定义的内容。
这个注册过程包括了两个部分,Bean的注册和别名的注册,别名的注册前面已经提到过了,这里就不详细说明了,主要来看一下Bean的注册。这个在XmlBeanFactory的继承树中也可以找到实现,它的基类org.springframework.beans.factory.support.DefaultListableBeanFactory就给出了具体的实现,源代码如下:
至此,XmlBeanFactory的初始化过程结束了,下面的章节来看一下它的Bean实例化过程是怎样的。
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); } }
可以来简单的看一下各个子标签的处理,首先是<import>
protected void importBeanDefinitionResource(Element ele) { // 获取<import>的resource属性,也就是需要导入的xml的名字 String location = ele.getAttribute(RESOURCE_ATTRIBUTE); if (!StringUtils.hasText(location)) { getReaderContext().error("Resource location must not be empty", ele); return; } // 处理系统属性,将"${...}"这种占位符替换成具体的值 location = SystemPropertyUtils.resolvePlaceholders(location); if (ResourcePatternUtils.isUrl(location)) {// 是否URL try { Set actualResources = new LinkedHashSet(4); // 这里同前面的过程一样,形成了一个载入xml的"递归" int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]"); } Resource[] actResArray = (Resource[]) actualResources .toArray(new Resource[actualResources.size()]); // 这个事件通知默认是空的,什么都不做 getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to import bean definitions from URL location [" + location + "]", ele, ex); } } else { // 非URL的处理过程与URL的类似 try { Resource relativeResource = getReaderContext().getResource().createRelative( location); int importCount = getReaderContext().getReader().loadBeanDefinitions( relativeResource); if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]"); } getReaderContext().fireImportProcessed(location, new Resource[] { relativeResource }, extractSource(ele)); } catch (IOException ex) { getReaderContext().error( "Invalid relative resource location [" + location + "] to import bean definitions from", ele, ex); } catch (BeanDefinitionStoreException ex) { getReaderContext().error( "Failed to import bean definitions from relative location [" + location + "]", ele, ex); } } }
这个就是<import>的大致处理过程了,如果有兴趣可以简单的看一下占位符的处理(org.springframework.util.SystemPropertyUtils#resolvePlaceholders()),我把注释后的代码也一并贴上。
public static String resolvePlaceholders(String text) { StringBuffer buf = new StringBuffer(text); // 占位符前缀"${" int startIndex = buf.indexOf(PLACEHOLDER_PREFIX); while (startIndex != -1) {// 存在占位符前缀 // 占位符后缀"}" int endIndex = buf.indexOf(PLACEHOLDER_SUFFIX, startIndex + PLACEHOLDER_PREFIX.length()); if (endIndex != -1) {// 存在占位符后缀 // 提取占位符内容 String placeholder = buf.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); // index移到占位符后缀处 int nextIndex = endIndex + PLACEHOLDER_SUFFIX.length(); try { // 获取系统属性值 String propVal = System.getProperty(placeholder); if (propVal == null) { propVal = System.getenv(placeholder); } if (propVal != null) { // 替换占位符 buf.replace(startIndex, endIndex + PLACEHOLDER_SUFFIX.length(), propVal); nextIndex = startIndex + propVal.length(); } else { System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + "] as system property: neither system property nor environment variable found"); } } catch (Throwable ex) { System.err.println("Could not resolve placeholder '" + placeholder + "' in [" + text + "] as system property: " + ex); } startIndex = buf.indexOf(PLACEHOLDER_PREFIX, nextIndex); } else { startIndex = -1; } } return buf.toString(); }
第二个是<alias>的处理
protected void processAliasRegistration(Element ele) { // 获得<alias>标签的"name"属性 String name = ele.getAttribute(NAME_ATTRIBUTE); // 获得<alias>标签的"alias"属性 String alias = ele.getAttribute(ALIAS_ATTRIBUTE); boolean valid = true; // name和alias是不是为空 if (!StringUtils.hasText(name)) { getReaderContext().error("Name must not be empty", ele); valid = false; } if (!StringUtils.hasText(alias)) { getReaderContext().error("Alias must not be empty", ele); valid = false; } if (valid) { try { // 注册alias getReaderContext().getRegistry().registerAlias(name, alias); } catch (Exception ex) { getReaderContext().error("Failed to register alias '" + alias + "' for bean with name '" + name + "'", ele, ex); } getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); } }
这里还存在一个疑点,就是注册alias的过程,这里详细写出来的话会比较长,暂时就不详细写查找getRegistry()方法返回是哪个类的实例的过程了。
直接给出结论吧,这里返回的BeanDefinitionRegistry接口的实现就是XmlBeanFactory类本身,而这个registerAlias()就要顺着继承树向上查找了,直到org.springframework.core.SimpleAliasRegistry类为止,这个类实现了registerAlias()方法。
public class SimpleAliasRegistry implements AliasRegistry { /** Map from alias to canonical name */ private final Map aliasMap = CollectionFactory.createConcurrentMapIfPossible(16); public void registerAlias(String name, String alias) { Assert.hasText(name, "'name' must not be empty"); Assert.hasText(alias, "'alias' must not be empty"); if (alias.equals(name)) {// alias和name相同 this.aliasMap.remove(alias); } else { if (!allowAliasOverriding()) { String registeredName = (String) this.aliasMap.get(alias); if (registeredName != null && !registeredName.equals(name)) { throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" + name + "': It is already registered for name '" + registeredName + "'."); } } // 在aliasMap中存放alias和name的entry this.aliasMap.put(alias, name); } } ...... }
至此,我们知道了alias的相关信息是放在SimpleAliasRegistry的一个成员变量aliasMap中存储的。
看完了<alias>标签后,最后来看一下最重要的<bean>标签的处理,对应的方法是#processBeanDefinition()
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 获得一个BeanDefinitionHolder对象 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { // 对Bean定义进行装饰 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 注册Bean定义 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
这里有两个重要的方法需要仔细研究,一个是BeanDefinitionParserDelegate的#parseBeanDefinitionElement(),另外一个是BeanDefinitionReaderUtils的#registerBeanDefinition。首先来看第一个
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { // 返回<bean>的"ID"属性 String id = ele.getAttribute(ID_ATTRIBUTE); // 返回<bean>的"name"属性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List aliases = new ArrayList(); if (StringUtils.hasLength(nameAttr)) { // 根据",",":"和" "来将name分割成数组 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS); // 追加别名到arraylist aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; // 如果ID属性没有值并且name属性不为空 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { // 用name属性第一个定义的别名来代替ID beanName = (String) aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } if (containingBean == null) { // 判断使用的ID和name是不是唯一的 checkNameUniqueness(beanName, aliases, ele); } // 分析<bean>的定义 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); if (beanDefinition != null) { if (!StringUtils.hasText(beanName)) { try { // 如果没有ID,那么生成一个 if (containingBean != null) { beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, this.readerContext.getRegistry(), true); } else { beanName = this.readerContext.generateBeanName(beanDefinition); String beanClassName = beanDefinition.getBeanClassName(); if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { // 注册bean的类名为别名 aliases.add(beanClassName); } } if (logger.isDebugEnabled()) { logger.debug("Neither XML 'id' nor 'name' specified - " + "using generated bean name [" + beanName + "]"); } } catch (Exception ex) { error(ex.getMessage(), ele); return null; } } // 返回BeanDefinitionHolder(不知道怎么翻译好) String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } return null; }
这个方法对<bean>标签进行了分析,其中有一个AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);这条语句是对<bean>标签的属性进行分析,可以来看一下它的源代码:
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) { // 一个保存解析状态的堆栈 this.parseState.push(new BeanEntry(beanName)); String className = null; // class属性 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { String parent = null; // parent属性 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } // bean定义 AbstractBeanDefinition bd = createBeanDefinition(className, parent); // 解析<bean>的属性 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); // 解析<meta>子标签 parseMetaElements(ele, bd); // 解析<lookup-method>子标签 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); // 解析<replaced-method>子标签 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); // 解析<constructor-arg>子标签 parseConstructorArgElements(ele, bd); // 解析<property>子标签 parsePropertyElements(ele, bd); // 解析<qualifier>子标签 parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); return bd; } catch (ClassNotFoundException ex) { error("Bean class [" + className + "] not found", ele, ex); } catch (NoClassDefFoundError err) { error("Class that bean class [" + className + "] depends on not found", ele, err); } catch (Throwable ex) { error("Unexpected failure during bean definition parsing", ele, ex); } finally { this.parseState.pop(); } return null; }
这里边包括了对<bean>标签下的所有属性和子标签的解析,很多细节就不详细的说明了,主要看看解析<bean>标签属性的函数吧,就是这个#parseBeanDefinitionAttributes()方法。
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) { if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {// scope属性 bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { error("Specify either 'scope' or 'singleton', not both", ele); } } else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {// singleton属性 // true的话是"singleton",否则是"prototype" bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE); } else if (containingBean != null) { bd.setScope(containingBean.getScope()); } if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {// abstract属性 bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); } // lazy-init属性 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) { // 如果lazy-init的值是default,并且bean是单例的,lazy-init对prototype没有意义 // 取得<beans>标签中默认指定的 lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); // autowire属性 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); // dependency-check属性 String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE); bd.setDependencyCheck(getDependencyCheck(dependencyCheck)); // depends-on属性,提前决定依赖 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS)); } // autowire-candidate属性,是否作为自动装配的候选者 String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); // autowire-candidate为空或者为"default"时 if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) { // 根据<beans>标签中的规则决定 String candidatePattern = this.defaults.getAutowireCandidates(); if (candidatePattern != null) { // 获得用逗号分开之后的匹配规则 String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); // 检验是否匹配 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); } } else { bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); } // primary属性,bean定义不唯一的情况下的首选自动装配Bean if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } // init-method属性 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); if (!"".equals(initMethodName)) { bd.setInitMethodName(initMethodName); } } else { if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); } } // destroy-method属性 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); if (!"".equals(destroyMethodName)) { bd.setDestroyMethodName(destroyMethodName); } } else { if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); } } // factory-method属性 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); } // factory-bean属性 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); } return bd; }
这里边包含了所有熟悉的属性定义。看完了标签的解析,下面就要来看一下前面提到的另外的bean的注册过程了,也就是BeanDefinitionReaderUtils的#registerBeanDefinition方法定义的内容。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException { // Bean注册 String beanName = definitionHolder.getBeanName(); registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); // Bean的别名注册 String[] aliases = definitionHolder.getAliases(); if (aliases != null) { for (int i = 0; i < aliases.length; i++) { registry.registerAlias(beanName, aliases[i]); } } }
这个注册过程包括了两个部分,Bean的注册和别名的注册,别名的注册前面已经提到过了,这里就不详细说明了,主要来看一下Bean的注册。这个在XmlBeanFactory的继承树中也可以找到实现,它的基类org.springframework.beans.factory.support.DefaultListableBeanFactory就给出了具体的实现,源代码如下:
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { Assert.hasText(beanName, "'beanName' must not be empty"); Assert.notNull(beanDefinition, "BeanDefinition must not be null"); if (beanDefinition instanceof AbstractBeanDefinition) { try { // 验证Bean的定义是否合法 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } // 在beanDefinitionMap这个Map中存放了Bean的名字(ID)与Bean定义的映射 synchronized (this.beanDefinitionMap) { Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!this.allowBeanDefinitionOverriding) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } else { if (this.logger.isInfoEnabled()) { this.logger.info("Overriding bean definition for bean '" + beanName + "': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]"); } } } else { this.beanDefinitionNames.add(beanName); this.frozenBeanDefinitionNames = null; } // 注册Bean定义 this.beanDefinitionMap.put(beanName, beanDefinition); resetBeanDefinition(beanName); } }
至此,XmlBeanFactory的初始化过程结束了,下面的章节来看一下它的Bean实例化过程是怎样的。
相关推荐
Spring.Demo项目很可能是包含一个简单的Spring.NET应用示例,可能包括了XML配置文件、服务接口和实现类、以及如何使用IoC容器来获取和使用这些对象的代码。通过这个示例,你可以更直观地了解如何在实际项目中运用...
在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...
Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务...
注解是Java语言提供的一种元数据机制,允许我们在源代码中嵌入信息,这些信息可以被编译器或者运行时环境解析和使用。Spring框架充分利用了这一特性,提供了一系列注解来简化配置,使得我们可以避免使用XML配置文件...
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...
当我们在Web环境中运行Spring应用时,IoC容器需要在Web容器(如Tomcat、Jetty等)中启动并运行。这个过程涉及到一系列的初始化步骤,确保Spring能够正确地与Web容器集成。 首先,`WebApplicationContext`是`...
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:...
#### 二、Spring IoC容器的搭建流程 根据题目中给出的部分内容,下面详细介绍如何基于Spring 3.0.5搭建一个简单的应用,并且使用Spring JDBC Template进行数据库交互。该教程将分为以下几个步骤: 1. **下载并配置...
Spring支持多种持久化技术,如JDBC、Hibernate、MyBatis等,可以利用IoC容器管理这些DAO对象,使它们能够依赖于事务管理、数据源等服务。 **工厂模式** 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳...
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配置的一种方式,它使得代码更加简洁、易读。例如,我们...