Spring核心源码详解:IoC容器与配置策略

2 下载量 201 浏览量 更新于2024-06-16 1 收藏 639KB PDF 举报
Spring框架的核心源码深入解读是理解其高效管理和组织企业级应用的关键。Spring的基石是IoC(Inversion of Control,控制反转)容器,它主要由ApplicationContext接口来实现。这个接口扮演着中心角色,负责初始化、配置和组装应用程序中的bean,也就是业务组件。 Spring提供了多种实现ApplicationContext的方式,针对不同的应用场景。对于独立应用,ClassPathXmlApplicationContext和FileSystemXmlApplicationContext是常用的选项,前者从类路径下读取XML配置文件,后者则从文件系统中加载。而在Web应用中,只需在web.xml中配置ContextLoaderListener,并指定XML文件的位置,Spring会自动创建WebApplicationContextIoC容器,为web层的bean提供服务。 配置元数据是Spring的核心元素,它定义了bean的实例化规则和依赖关系。Spring支持三种主要的配置方式: 1. 基于XML配置:这是最传统的形式,使用`<bean>`元素明确地声明bean的属性和依赖,结构清晰,易于理解和维护。 2. 基于Java代码配置:通过`@Configuration`注解标记类,使得配置与实际业务逻辑更加紧密,无需外部XML文件,简化了开发过程。 3. 基于Java注解配置:利用Spring提供的`@Component`, `@Autowired`, `@Qualifier`等注解,可以在类上或字段上直接声明依赖关系,减少了XML的使用量,提高了灵活性。 实例化容器的过程相对直接,开发者只需要提供配置文件的路径,或者通过ApplicationContext的构造函数传入所需的资源。例如,如下的代码展示了如何使用ClassPathXmlApplicationContext: ```java ApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); ``` `refresh()`方法是ApplicationContext的主要入口,用于初始化整个bean的生命周期。内部包含了`loadBeanDefinitions()`方法,这个方法的主要职责是加载并解析配置文件,最终构建一个`ConfigurableListableBeanFactory`,这是用于实例化bean的工厂。 `refresh()`方法的具体实现涉及一系列步骤,如准备刷新环境、获取可配置的BeanFactory实例(如`DefaultListableBeanFactory`),然后执行初始化操作,确保所有bean在运行时能够正确装配和初始化。这个过程体现了Spring的核心设计思想,即将复杂性封装在底层,对外提供简单易用的API。 Spring的核心源码深入研究可以帮助我们理解其设计哲学和实现细节,这对于开发者来说是提升技能、优化代码结构和解决生产环境中问题的重要途径。通过掌握这些核心概念,我们可以更好地利用Spring进行高效、灵活的组件管理和依赖注入。
2013-06-15 上传
代码解析2,部分摘抄 简单的说,在web容器中,通过ServletContext为Spring的IOC容器提供宿主环境,对应的建立起一个IOC容器的体系。其中,首先需要建立的是根上下文,这个上下文持有的对象可以有业务对象,数据存取对象,资源,事物管理器等各种中间层对象。在这个上下文的基础上,和web MVC相关还会有一个上下文来保存控制器之类的MVC对象,这样就构成了一个层次化的上下文结构。在web容器中启动Spring应用程序就是一个建立这个上下文体系的过程。Spring为web应用提供了上下文的扩展接口 WebApplicationContext: 如转载请注明,转载自:关注Java[http://www.gbsou.com] 本文链接: http://www.gbsou.com/2009/08/11/214.html - - Java代码 public interface WebApplicationContext extends ApplicationContext { //这里定义的常量用于在ServletContext中存取根上下文 String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; …… //对WebApplicationContext来说,需要得到Web容器的ServletContext ServletContext getServletContext(); } public interface WebApplicationContext extends ApplicationContext { //这里定义的常量用于在ServletContext中存取根上下文 String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT"; ...... //对WebApplicationContext来说,需要得到Web容器的ServletContext ServletContext getServletContext(); } 而一般的启动过程,Spring会使用一个默认的实现,XmlWebApplicationContext – 这个上下文实现作为在web容器中的根上下文容器被建立起来,具体的建立过程在下面我们会详细分析。 Java代码 public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** 这是和web部署相关的位置信息,用来作为默认的根上下文bean定义信息的存放位置*/ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { //对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } //使用XmlBeanDefinitionReader来读入bean定义信息 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (int i = 0; i < configLocations.length; i++) { reader.loadBeanDefinitions(configLocations[i]); } } } //这里取得bean定义信息位置,默认的地方是/WEB-INF/applicationContext.xml protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** 这是和web部署相关的位置信息,用来作为默认的根上下文bean定义信息的存放位置*/ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; //我们又看到了熟悉的loadBeanDefinition,就像我们前面对IOC容器的分析中一样,这个加载工程在容器的refresh()的时候启动。 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException { //对于XmlWebApplicationContext,当然使用的是XmlBeanDefinitionReader来对bean定义信息来进行解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); loadBeanDefinitions(beanDefinitionReader); } protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) { } //使用XmlBeanDefinitionReader来读入bean定义信息 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { String[] configLocations = getConfigLocations(); if (configLocations != null) { for (int i = 0; i < configLocations.length; i++) { reader.loadBeanDefinitions(configLocations[i]); } } } //这里取得bean定义信息位置,默认的地方是/WEB-INF/applicationContext.xml protected String[] getDefaultConfigLocations() { if (getNamespace() != null) { return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX}; } else { return new String[] {DEFAULT_CONFIG_LOCATION}; } } } 对于一个Spring激活的web应用程序,可以通过使用Spring代码声明式的指定在web应用程序启动时载入应用程序上下文(WebApplicationContext),Spring的ContextLoader是提供这样性能的类,我们可以使用 ContextLoaderServlet或者ContextLoaderListener的启动时载入的Servlet来实例化Spring IOC容器 – 为什么会有两个不同的类来装载它呢,这是因为它们的使用需要区别不同的Servlet容器支持的Serlvet版本。但不管是 ContextLoaderSevlet还是 ContextLoaderListener都使用ContextLoader来完成实际的WebApplicationContext的初始化工作。这个ContextLoder就像是Spring Web应用程序在Web容器中的加载器booter。当然这些Servlet的具体使用我们都要借助web容器中的部署描述符来进行相关的定义。 下面我们使用ContextLoaderListener作为载入器作一个详细的分析,这个Servlet的监听器是根上下文被载入的地方,也是整个 Spring web应用加载上下文的第一个地方;从加载过程我们可以看到,首先从Servlet事件中得到ServletContext,然后可以读到配置好的在web.xml的中的各个属性值,然后ContextLoder实例化WebApplicationContext并完成其载入和初始化作为根上下文。当这个根上下文被载入后,它被绑定到web应用程序的ServletContext上。任何需要访问该ApplicationContext的应用程序代码都可以从WebApplicationContextUtils类的静态方法来得到: