导航:首页 > 源码编译 > springbean源码

springbean源码

发布时间:2023-08-02 23:14:38

⑴ spring 3源码解析之如何解析"import", "alias", "bean"标签

解析的步骤: 1、加载web.xml、加载监听器org.springframework.web.context.ContextLoaderListener 2、ContextLoaderListener 初始化initWebApplicationContext方法创建 org.springframework.web.context.support. XmlWebApplicationContext对象 3、XmlWebApplicationContext调用loadBeanDefinitions方法,该方法主要做两件事情:初始化XmlBeanDefinitionReader、获取applicationContext.xml配置文件的路径、然后把事情交给XmlBeanDefinitionReader来处理 4、XmlBeanDefinitionReader获取到applicationContext.xml配置文件的路径、读取配置文件的内容得到一个输入流、对输入流转码操作、然后封装成一个inputSource对象、再然后封装成一个document对象;在生成document对象的同事也生成了一个Resource对象、这两个对象分部是:document对象承载配置文件的主要内容信息、Resource承载配置文件的描述信息以及一些验证信息。 再由Resource对象创建一个XmlReaderContext。完成了以上操作XmlBeanDefinitionReader就把document对象和XmlReaderContext对象交给来处理 5、1)、对XmlReaderContext装饰成一个BeanDefinitionParserDelegate对象; 2)、迭代document对象、把document对象拆分成Element元素逐个逐个解析; 3)、使用BeanDefinitionParserDelegate装饰对象解析Element元素或者说标签。 if (absoluteLocation) { try { int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from URL location [" + location + "]"); } } catch (BeanDefinitionStoreException ex) { getReaderContext().error( "Failed to import bean definitions from URL location [" + location + "]", ele, ex); } } else { // No URL -> considering resource location as relative to the current file. try { int importCount; Resource relativeResource = getReaderContext().getResource().createRelative(location); if (relativeResource.exists()) { importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); actualResources.add(relativeResource); } else { String baseLocation = getReaderContext().getResource().getURL().toString(); importCount = getReaderContext().getReader().loadBeanDefinitions( StringUtils.applyRelativePath(baseLocation, location), actualResources); } if (logger.isDebugEnabled()) { logger.debug("Imported " + importCount + " bean definitions from relative location [" + location + "]"); } } catch (IOException ex) { getReaderContext().error("Failed to resolve current resource location", ele, ex); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to import bean definitions from relative location [" + location + "]", ele, ex); } } Resource[] actResArray = actualResources.toArray(new Resource[actualResources.size()]); getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); } 解析alias标签的方法:

⑵ 如何查看spring源码

1.准备工作:在官网上下载了Spring源代码之后,导入Eclipse,以方便查询。
2.打开我们使用Spring的项目工程,找到Web.xml这个网站系统配置文件,在其中找到Spring的初始化信息:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

由配置信息可知,我们开始的入口就这里ContextLoaderListener这个监听器。
在源代码中我们找到了这个类,它的定义是:
public class ContextLoaderListener extends ContextLoader
implements ServletContextListener {

/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
...
}

该类继续了ContextLoader并实现了监听器,关于Spring的信息载入配置、初始化便是从这里开始了,具体其他阅读另外写文章来深入了解。
二、关于IOC和AOP
关于Spring IOC 网上很多相关的文章可以阅读,那么我们从中了解到的知识点是什么?
1)IOC容器和AOP切面依赖注入是Spring是核心。
IOC容器为开发者管理对象之间的依赖关系提供了便利和基础服务,其中Bean工厂(BeanFactory)和上下文(ApplicationContext)就是IOC的表现形式。BeanFactory是个接口类,只是对容器提供的最基本服务提供了定义,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具体的实现。
接口:

public interface BeanFactory {
//这里是对工厂Bean的转义定义,因为如果使用bean的名字检索IOC容器得到的对象是工厂Bean生成的对象,
//如果需要得到工厂Bean本身,需要使用转义的名字来向IOC容器检索
String FACTORY_BEAN_PREFIX = "&";
//这里根据bean的名字,在IOC容器中得到bean实例,这个IOC容器就象一个大的抽象工厂,用户可以根据名字得到需要的bean
//在Spring中,Bean和普通的java对象不同在于:
//Bean已经包含了我们在Bean定义信息中的依赖关系的处理,同时Bean是已经被放到IOC容器中进行管理了,有它自己的生命周期
Object getBean(String name) throws BeansException;
//这里根据bean的名字和Class类型来得到bean实例,和上面的方法不同在于它会抛出异常:如果根名字取得的bean实例的Class类型和需要的不同的话。
Object getBean(String name, Class requiredType) throws BeansException;
//这里提供对bean的检索,看看是否在IOC容器有这个名字的bean
boolean containsBean(String name);
//这里根据bean名字得到bean实例,并同时判断这个bean是不是单件,在配置的时候,默认的Bean被配置成单件形式,如果不需要单件形式,需要用户在Bean定义信息中标注出来,这样IOC容器在每次接受到用户的getBean要求的时候,会生成一个新的Bean返回给客户使用 - 这就是Prototype形式
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//这里对得到bean实例的Class类型
Class getType(String name) throws NoSuchBeanDefinitionException;
//这里得到bean的别名,如果根据别名检索,那么其原名也会被检索出来
String[] getAliases(String name);
}

实现:
XmlBeanFactory的实现是这样的:
public class XmlBeanFactory extends DefaultListableBeanFactory {
//这里为容器定义了一个默认使用的bean定义读取器,在Spring的使用中,Bean定义信息的读取是容器初始化的一部分,但是在实现上是和容器的注册以及依赖的注入是分开的,这样可以使用灵活的 bean定义读取机制。
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//这里需要一个Resource类型的Bean定义信息,实际上的定位过程是由Resource的构建过程来完成的。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//在初始化函数中使用读取器来对资源进行读取,得到bean定义信息。这里完成整个IOC容器对Bean定义信息的载入和注册过程
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

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

       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 继承了 并实现了 以及 BeanDefinitionRegistry 接口。

        Spring的配置文件读取是通过ClasaPathResource进行封装的 ,如:new ClassPathResource("bean.xml")。在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事件监听机制源码解析

1.Spring事件监听体系包括三个组件:事件、事件监听器搜哪,事件广播器。

事件:定义事件类型和事件源,需要继承ApplicationEvent。

事件监听器:用来监听某一类的事件,并且执行具体业务逻辑,需要实现ApplicationListener 接口或者需要用@ListenerEvent(T)注解。好比观察者模式中的观察者。

事件多播器:负责广播通知所有监听器,所有的事件监听判猛器都注册在了事件多播器中。好比观察者模式中的被观察者。Spring容器默认生成的是同步事件多播器。可以自定义事件多播器,定义为异步方式。

创建 的过程中,会执行refresh()中的()方法。该方法先获取bean工厂,然后判断工厂是否包含了beanName 为 applicationEventMulticaster的bean。如果包含了,则获取该bean,赋值给applicationEventMulticaster 属性。如果没有,则创建一个 对象,并且赋值给 applicationEventMulticaster 。实现了源码如下:

监听器的注册有两种,通过实现 ApplicationListener接口或者添加@EventListener注解。

注册的逻辑实现在refresh()中的registerListeners()方法里面。第一步,先获取当前ApplicationContext中已经添加的 applicationListeners(SpringMVC源码中有用到),遍历添加到多播器中。第二步,获取实现了ApplicationListener接口的listenerBeanNames集合,添加至多掘漏桥播器中。第三步,判断是否有早期事件,如果有则发起广播。

思考一下,上面的代码中第二步为啥添加的是listenerBeanName?

如果监听器是懒加载的话(即有@Lazy 注解)。那么在这个时候创建监听器显然是不对的,这个时候不能创建监听器。所以添加监听器到多播器的具体逻辑放在初始化具体的监听器之后。通过 BeanPostProcessor 的接口实现。具体的实现类是 ApplicationListenerDetector 。这个类是在 refreah()中prepareBeanFactory()方法中添加的。代码如下:

在创建 的构造方法中,会执行org.springframework.context.annotation.AnnotationConfigUtils#(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 方法。这个方法中会添加两个 beanDefs, 代码如下:

EventListenerMethodProcessor:事件监听器的BeanFactory后置处理器,在前期会创建 DefaultEventListenerFactory ,后期在创建好Bean之后,根据 EventListener 属性,调用DefaultEventListenerFactory创建具体的 。

DefaultEventListenerFactory:监听器的创建工厂,用来创建 。

EventListenerMethodProcessor 的类继承图如下:

在refreash的()中会调用 org.springframework.context.event.EventListenerMethodProcessor#postProcessBeanFactory方法,获取EventListenerFactory 类型的 Bean。代码如下:

在 org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons 方法中,创建完所有的单例Bean 之后,会遍历所有Bean是否实现了 SmartInitializingSingleton 接口。如果实现接口会执行该 Bean 的 afterSingletonsInstantiated() 方法。代码如下:

org.springframework.context.event.EventListenerMethodProcessor#afterSingletonsInstantiated 中会调用私有方法 processBean()进行 ApplicationEventAdatper 的创建。代码如下:

可以通过调用 org.springframework.context.support.AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType) 方法进行事件的调用。代码如下:

中的 multicasEvent,invokeListener,doInvokeListener 三个方法代码如下:

SpringMVC中就是通过Spring的事件机制进行九大组件的初始化。

监听器定义在FrameworkServlet类中,作为内部类。代码如下:

监听器的添加在org.springframework.web.servlet.FrameworkServlet# 中进行。通过SourceFilteringListener进行包装。添加代码如下:

在refresh中的registerListeners方法进行添加,代码如下:

在refresh中的finishRefresh()方法中,会调用publishEvnet(new ContextRefreshedEvent(this))发布事件。进行多播器广播,代码如下

最终会调到FrameworkServlet.this.onApplicationEvent(event)。

阅读全文

与springbean源码相关的资料

热点内容
对外汉语pdf 浏览:514
如何用mamp本地web服务器 浏览:869
如何加密自己js代码 浏览:623
排列组合a与c的算法 浏览:534
如何在文件夹中找到同名内容 浏览:786
有什么app文字转韩文配音 浏览:372
循环宏1命令 浏览:35
斐波那契数列矩阵算法 浏览:674
公式保护后加密不了 浏览:82
java跳转到jsp 浏览:819
327平方根算法 浏览:216
win7美化命令行终端 浏览:797
免加密狗图片 浏览:485
一只透明的鸟是什么app 浏览:817
空气压缩机油批发商 浏览:69
linuxifexist 浏览:4
加密tf卡拷入文件 浏览:399
山西php工资 浏览:673
福州看病预约用什么小程序app 浏览:238
php保留两位小数不四舍五入 浏览:292