`
zddava
  • 浏览: 243706 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring源代码分析 -- IOC容器(二)

阅读更多
上一篇文章讲到了对<import>,<alias>,<bean>标签处理的方法org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#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);
		}
	}


可以来简单的看一下各个子标签的处理,首先是<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.net二----初探IOC容器.rar源代码

    Spring.Demo项目很可能是包含一个简单的Spring.NET应用示例,可能包括了XML配置文件、服务接口和实现类、以及如何使用IoC容器来获取和使用这些对象的代码。通过这个示例,你可以更直观地了解如何在实际项目中运用...

    Spring源代码解析(一):IOC容器.doc

    在Spring源代码解析的第一部分,我们将聚焦于IOC容器,特别是BeanFactory接口,它是所有Spring容器的基础。 BeanFactory接口是Spring的基石,它定义了基本的容器操作,如获取Bean、检查Bean是否存在、确定Bean的...

    Spring源代码解析

    Spring源代码解析(二):IoC容器在Web容器中的启动 Spring源代码解析(三):Spring JDBC Spring源代码解析(四):Spring MVC Spring源代码解析(五):Spring AOP获取Proxy Spring源代码解析(六):Spring声明式事务...

    spring-demo10-注解-IOC.zip

    注解是Java语言提供的一种元数据机制,允许我们在源代码中嵌入信息,这些信息可以被编译器或者运行时环境解析和使用。Spring框架充分利用了这一特性,提供了一系列注解来简化配置,使得我们可以避免使用XML配置文件...

    Spring源代码解析.rar

    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...

    Spring源代码解析(二):IoC容器在Web容器中的启动.doc

    当我们在Web环境中运行Spring应用时,IoC容器需要在Web容器(如Tomcat、Jetty等)中启动并运行。这个过程涉及到一系列的初始化步骤,确保Spring能够正确地与Web容器集成。 首先,`WebApplicationContext`是`...

    Spring2.5.6源代码分析(一):IOC容器

    IoC容器是Spring框架的心脏,它负责管理对象的生命周期和依赖关系,使得开发者能够实现松耦合和高可测试性的应用程序。 首先,我们来理解什么是IoC。IoC,也被称为依赖注入(Dependency Injection),是一种设计...

    Spring 源代码解析

    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 IoC容器的搭建流程 根据题目中给出的部分内容,下面详细介绍如何基于Spring 3.0.5搭建一个简单的应用,并且使用Spring JDBC Template进行数据库交互。该教程将分为以下几个步骤: 1. **下载并配置...

    Spring-IoC 容器 - v1.01

    Spring支持多种持久化技术,如JDBC、Hibernate、MyBatis等,可以利用IoC容器管理这些DAO对象,使它们能够依赖于事务管理、数据源等服务。 **工厂模式** 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳...

    springIOC核心组件分析.vsdx

    spring-context:上下文,即IOC容器 spring-context-support:对IOC的扩展,以及IOC子容器 spring-context-indexer:类管理组件和Classpath扫描 spring-expression:表达式语句 切面编程: spring-aop:面向切面编程,...

    spring-framework-2.5-rc2-with-dependencies\spring-framework-2.5-rc2\spring-framework-2.5-rc2源代码

    通过阅读和学习这些源码,开发者可以了解到Spring如何实现IoC容器、AOP代理、事件机制、任务调度等多个关键功能。同时,这也有助于开发者更好地理解和使用Spring提供的API,以及在实际项目中如何定制和扩展Spring。 ...

    SpringIOC示例源代码

    3. `TestIoC.java`:这是一个关于IoC容器的测试类,它可能使用Spring的ApplicationContext接口来加载bean.xml配置,然后通过容器获取并测试bean实例。 4. `ServiceBean.java`:这可能是一个通用的服务bean,用于...

    spring-webmvc-struts.jar

    例如,`StrutsActionProxy`类是如何拦截Struts的请求,然后通过Spring的IoC容器查找并调用对应的bean方法。同时,源代码中还展示了如何将Struts的配置信息与Spring的bean定义相结合,实现配置的统一管理和重用。 ...

    spring-context-3.2.0 spring-core-3.2.0 等齐全的Spring jar包

    这里提到的是一组完整的Spring库,包括`spring-core`、`spring-context`、`spring-webmvc`、`spring-web`、`spring-beans`、`spring-test`、`spring-jdbc`、`spring-orm`、`spring-aop`和`spring-tx`,它们都是3.2.0...

    spring源代码解析

    2. **Web环境下的IOC容器启动**:"spring源代码解析(二):IOC容器在web中启动.doc"涵盖了在Web应用中初始化Spring容器的过程,包括ApplicationContext的创建、DispatcherServlet的配置以及如何在Web环境中注入bean...

    spring核心技术源代码spring核心技术源代码1-9章

    通过阅读并分析这些源代码,开发者可以更深入地理解Spring框架的工作机制,学习如何有效地使用其特性来提高代码的可维护性和可扩展性。每个章节都会提供实际的示例,帮助开发者将理论知识转化为实践技能。对于想要...

    Spring IoC简单示例-注解配置-Maven构建

    Spring IoC容器通过解析XML配置文件或使用注解来识别对象及其依赖关系,并在运行时自动装配这些对象,这就是依赖注入。 在Spring中,注解配置是取代传统XML配置的一种方式,它使得代码更加简洁、易读。例如,我们...

Global site tag (gtag.js) - Google Analytics