Spring源码解析(一)- 容器的基本实现

Spring源码解析(一)- 容器的基本实现,第1张

       Spring使用 基本的JavaBean 来完成以前只可能由EJB完成的事情,是个分层架构。Spring创建bean都需要通过 读取 、 解析 、 校验配置文件, 然后注册创建成Bean。 Spring是一个Bean容器 , 主要作用是替我们管理bean对象 (简单的Java类对象的生命周期)。不管框架如何强大,还是需要我们程序员来告诉其一些必要信息的(比如要 管理的bean对象的类相关信息、是否开启组件扫描 等),这些我们称之为对 Spring框架的配置 ,目前主流的配置方式是 通过使用配置文件或注解。

        Spring中最核心的两个类: DefaultListableBeanFactory、XmlBeanDifinitionReader。DefaultListableBeanFactory 是整个bean加载的核心部分,是Spring注册及加载bean的默认实现 。XmlBeanDefinitionReader 主要使用reader属性对资源文件进行读取和注册。

        XML配置文件读取是Spring中重要的功能,大部分Spring大部分功能都是 以配置作为切入点 。 XmlBeanFactory 继承自 DefaultListableBeanFactory ,而对于 DefaultListableBeanFactory 不同的地方其实是在 XmlBeanFactory 中使用了自定义的XML读取器 XmlBeanDefinitionReader ,主要用于从XML文档中读取 BeanDefinition, 实现了个性化的 BeanDefinitionReader 读取, DefaultListableBeanFactory 继承了 AbstractAutowireCapableBeanFactory 并实现了 ConfigurableListableBeanFactory 以及 BeanDefinitionRegistry 接口。

        Spring的配置文件读取是通过ClasaPathResource进行封装的 ,如:new ClassPathResource("beanxml")。在java中, 将不同来源的资源的读取逻辑抽象成URL ,通过注册不同的 handler来处理。 一般handler的类型使用不同的前缀,URL没有默认定义相对的path路径,也 没有提供相关方法对资源进行检查 ,顾Spring对其内部需要使用到的资源做了属于自己的抽象结构, 用Resource接口来封装底层资源。

        Resource 接口继承 InputStreamSource(封装了任何能返回InputStream的类)。

        Resource接口抽象了所有Spring内部使用到的底层资源 ,首先它定义了3个能判断当前资源状态的方法: 存在性(exists)、可读性(isReadable)、是否处于打开状态(isOpen) 。有了Resource接口便可以对所有资源进行统一处理。 ClassPathResource 中的实现是通过class或 classLoader 提供的底层方法进行调用。以此完成对配置文件资源的封装。

        当通过Resource相关类完成了对配置文件进行封装,接下来由 XmlBeanDefinitionReader 完成对配置文件的读取工作。

       XML文件的验证模式有两种:DTD、XSD(XML Schema)

        DTD即文档类型定义, 是一种XML约束模式语言,是XML文件的验证机制 。是一种保证XML文档格式正确的有效方法, 可以通过比较XML文档和DTD文件来查看文档是否符合规范,元素和标签的使用是否正确 。一个DTD文档包含:元素的定义规则、元素间关系的定义规则、元素可使用的属性、可使用的实体或符号规则。 要使用DTD验证模式需要在XML文件的头部声明。

        XML Schema语言就是XSD。   XML Schema描述了XML文档的结构。可以用一个指定的XML Schema来验证某个XML文档,以检查该XML文档是否符合其要求。也可以 通过XML Schema指定一个XML文档所允许的结构和内容 。XML Schema本身也是一个XML文档,符合XML语法结构,可以用通用的XML解析器解析它。    

        使用XML Schema文档对XML实例进行校验,要声明名称空间和指定该名称空间所对应的XML Schema文档存储位置 。通过schemaLocation属性来指定名称空间所对应的XML Schema文档的存储地址(1、名称空间URL;2、该名称空间所标识的XML Schema文件地址或URL地址)。

      另外验证模式通过 XmlBeanDefinitionReader 中的setValidationMode方法进行设定。而 Spring 用来检测验证模式的方法实际上就是判断是否包含 DOCTYPE ,如果包含就是 DTD ,否则就是 XSD 。

        XML文件经过验证模式,交由DocumentLoader进行解析成对应的 Document。 而解析的过程中存在这么一环节:(EntityResolver) 根据声明去寻找对应的DTD定义,以便对文档进行验证认证 。也可以通过setEntityResolver设置DTD定义。EntityResolver它用来接收两个参数publicId和systemId,xsd格式文件通常publicId为null。而对于不同的验证模式采用不同的解析器进行解析,并把文件转换成Document文件,用于提取及注册bean。

          Document 文件通过 BeanDefinitionDocumentReader 进行内部逻辑处理,并提取root用于作为参数继续完成BeanDefinition的注册。

一 什么是Spring

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架

二 如何在程序中获取Spring配置的bean呢

方法一 在初始化时保存ApplicationContext对象

代码

ApplicationContext ac = new FileSystemXmlApplicationContex( applicationContext xml );     ac getBean( beanId );

ApplicationContext ac = new FileSystemXmlApplicationContex( applicationContext xml );

ac getBean( beanId );说明 这种方式适用于采用Spring框架的独立应用程序 需要程序通过配置文件手工初始化Spring的情况

方法二 通过Spring提供的工具类获取ApplicationContext对象

代码

import sprntext support WebApplicationContextUtils;      ApplicationContext ac = WebApplicationContextUtils                                 getRequiredWebApplicationContext(ServletContext sc)      ApplicationContext ac = WebApplicationContextUtils                                 getWebApplicationContext(ServletContext sc)      ac getBean( beanId );      ac getBean( beanId );   import sprntext support WebApplicationContextUtils;      ApplicationContext ac = WebApplicationContextUtils                                 getRequiredWebApplicationContext(ServletContext sc)      ApplicationContext ac = WebApplicationContextUtils                                 getWebApplicationContext(ServletContext sc)      ac getBean( beanId );      ac getBean( beanId );

方法三 继承自抽象类ApplicationObjectSupport

说明 抽象类ApplicationObjectSupport提供getApplicationContext()方法 可以方便的获取到ApplicationContext Spring初始化时 会通过该抽象类的setApplicationContext(ApplicationContext context)方法将ApplicationContext 对象注入

方法四 继承自抽象类WebApplicationObjectSupport

说明 类似方法三 调用getWebApplicationContext()获取WebApplicationContext

方法五 实现接口ApplicationContextAware

lishixinzhi/Article/program/Java/ky/201311/28587

spring 怎么获取webxml中的context Spring配置文件在类路径下面 在Spring的java应用程序中,一般我们的Spring的配置文件都是放在放在类路径下面(也即编译后会进入到classes目录下)。 以下的项目,因为是用maven管理的

这样xml中配置的bean的属性就会被注入配置文件里面对应的值

首先xml中的bean会在扫描的过程中封装成BeanDefinition对象,property标签会被弄成一个ProprotyValue的集合放在BeanDefinition的ProprotyValues变量中,所以在xml解析完成之后的BeanDefinition的ProprotyValues变量是这样的

上节PropertySourcesPlaceholderConfigurer这个类收集了environment配置信息和本地配置信息,并把它放在了PropertySourcesPropertyResolver的propertySources属性中

最后创建了一个StringValueResolver对象会调用PropertySourcesPropertyResolver来处理配置信息的替换

接下来就是取出所有的BeanDefinition,看看beanDefinition中的属性中是否有${}表达式,有的话就替换

很多的属性都可以用${}来引用配置信息

重点看看属性是如何被替换的

在BeanDefinitionVisitorresolveValue方法中,String类型的走这

最终会调到PropertySourcesPlaceholderConfigurer创建的StringValueResolver匿名对象的实现方法中

这个匿名对象实现的方法又会调用PropertySourcesPropertyResolver来替换值,前面有提到所有的配置信息都在PropertySourcesPropertyResolverpropertySources中,那么接下来的工作就是从这个容器中找到对应的配置信息的key所对应的value

这里在入参时会创建一个PlaceholderResolver的匿名对象,实现的resolvePlaceholder方法将会调用PropertySourcesPropertyResolvergetPropertyAsRawString()

最后返回了被替换成对应配置信息的值

这里就会调用前面创建的匿名对象的实现方法,方法体重会调用调用PropertySourcesPropertyResolvergetPropertyAsRawString(),去用key获取对应的配置信息

PropertySourcesPropertyResolvergetPropertyAsRawString()

PropertiesPropertySource对象内部有name,和source,source是一个泛型,当前类型为Properties,PropertiesPropertySource需要实现getProperty方法,其实就是从source中获取属性值

最后调到了Properties类的get方法,返回value

对每个beanDefination都这样 *** 作过一遍

注意这个StringValueResolver的resolveStringValue会调用PropertySourcesPropertyResolver的方法来处理配置信息的替换,PropertySourcesPropertyResolver持有了所有的配置信息。 那么后面@Value的解析也将StringValueResolver来完成

@Value的解析工作是在Bean实例化后,属性注入的时候从配置文件找出并设置进去的

populateBean方法

只有string类型的才能@Value注解,才需要处理

又是这个容器,之前PropertySourcesPlaceholderConfigurer的doProcessProperties放进去的StringValueResolver

最后又会回到这个地方解析并注入值,和xml方式获取配置信息是一样的

找到对应的配置信息之后,反射设置这个属性的值

不用配置xml,直接java代码实现,参考代码如下:public class GetApplicationContext {private static class ApplicationContextHolder {// 单例变量private static ApplicationContext AC = new FileSystemXmlApplicationContext("classpath:applicationContextxml");}// 私有化的构造方法,保证外部的类不能通过构造器来实例化。private GetApplicationContext() {}// 获取单例对象实例public static ApplicationContext getInstance() {if (ApplicationContextHolderAC == null) {ApplicationContextHolderAC = new FileSystemXmlApplicationContext("classpath:applicationContextxml");}return ApplicationContextHolderAC;}}获取所有spring自动装配的bean://获取spring装配的bean个数GetApplicationContextgetInstance()getBeanDefinitionNames()length;//逐个打印出spring自动装配的bean。根据我的测试,类名第一个字母小写即bean的名字for(int i=0;i<33;i++){Systemoutprintln( GetApplicationContextgetInstance()getBeanDefinitionNames()[i]);}然后通过下面的代码获取到spring注解装配的bean供自己使用:StorageReturnService ossService = (StorageReturnService) GetApplicationContextgetInstance()getBean("storageReturnServiceImpl");怎样获取 spring 已经注解的bean

以上就是关于Spring源码解析(一)- 容器的基本实现全部的内容,包括:Spring源码解析(一)- 容器的基本实现、Java中如何获取Spring中配置的bean、spring web中control怎样获取xml中的bean等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9690618.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-01
下一篇2023-05-01

发表评论

登录后才能评论

评论列表(0条)

    保存