`
wantongliu
  • 浏览: 8513 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

第八本书 spring源码的入手

阅读更多

建议买一本spring源码深度解析

一本《SPRING技术内幕:深入解析SPRING架构与设计原理》

 

 

作者:者年
链接:https://www.zhihu.com/question/21346206/answer/83795226
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一,最基本
1. 了解 Java语法
2. 了解设计模式

二,项目基础
1. 已经了解 Spring Core 的功能
2. 已经过了一遍 public api
3. 已经根据自己对 IoC container 的理解,实现了一个最简单的 IoC container满足了之后,再进入 spring-core 和 spring-beans



 STEP1-10

 

作者:潜龙勿用
链接:https://www.zhihu.com/question/21346206/answer/221808473
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在阅读spring源码之前要明确两个问题:

1.阅读源码的入口在哪里?

2.入门前必备知识了解:IOC和AOP

一、我们从哪里开始

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);

}

 

我们可以看到IOC容器使用的一些基本过程:

如:DefaultListableBeanFactory

 

ClassPathResource res = new ClassPathResource("beans.xml");//读取配置文件

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

reader.loadBeanDefinitions(res);

 

<noscript>&amp;lt;img src="https://pic2.zhimg.com/50/v2-b8ed7b2867b6ccb85194848951791786_hd.jpg" data-rawwidth="600" data-rawheight="279" class="origin_image zh-lightbox-thumb" width="600" data-original="https://pic2.zhimg.com/v2-b8ed7b2867b6ccb85194848951791786_r.jpg"&amp;gt;</noscript>

 

这些代码演示了以下几个步骤:

1. 创建IOC配置文件的抽象资源

2. 创建一个BeanFactory,这里我们使用DefaultListableBeanFactory

3. 创建一个载入bean定义信息的读取器,这里使用XmlBeanDefinitionReader来载入XML形式

的bean定义信息,配置给BeanFactory

4. 从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成,这

样完成整个载入和注册bean定义的过程。我们的IoC容器就建立起来了。

再简单的说,我的系统在启动时候,会完成的动作就是

1.由ResourceLoader获取资源文件,也即bean的各种配置文件

2.由BeanDefintion对配置文件的定义信息的载入

3.用BeanDefinitionRegistry接口来实现载入bean定义信息并向IOC容器进行注册。

注意,IOC容器和上下文的初始化一般不包含Bean的依赖注入的实现。

2)AOP这个过程并不是在注册bean的过程实现的。

我们只看到在处理相关的Bean属性的时候,使用了RuntimeBeanReference对象作为依赖信息的纪录。

在IOC容器已经载入了用户定义的Bean信息前提下,这个依赖注入的过程是用户第一次向IOC容器索要Bean的时候触发的,或者是我们可以在Bean定义信息中通过控制lazy-init属性来使得容器完成对Bean的预实例化 - 这个预实例化也是一个完成依赖注入的过程。

我们说明一下过程:

1.用户想IOC容器请求Bean。

2.系统先在缓存中查找是否有该名称的Bean(去各个BeanFactory去查找)

3.没有的话就去创建Bean并进行依赖注入,并且这个请求将被记录起来。

请求Bean具体的实现:

代码入口在DefaultListableBeanFactory的基类AbstractBeanFactory中:

 

public Object getBean(String name, Class requiredType, final Object[] args) throwsBeansException {

...

Object sharedInstance = getSingleton(beanName);//先去缓存取

if (sharedInstance != null) {

...

if (containsBeanDefinition(beanName)) {

RootBeanDefinition mergedBeanDefinition = getMergedBeanDefinition(beanName, false);

bean = getObjectForBeanInstance(sharedInstance, name,mergedBeanDefinition);

}

else {

bean = getObjectForBeanInstance(sharedInstance, name, null);

}

}

else {

}

 

...

}

 

注入Bean具体的实现:

具体的bean创建过程和依赖关系的注入在createBean中,这个方法在AbstractAutowireCapableBeanFactory中给出了实现:

 

protected Object createBean(String beanName, RootBeanDefinition

mergedBeanDefinition, Object[] args)

throws BeanCreationException {

// Guarantee initialization of beans that the current one depends on.

// 这里对取得当前bean的所有依赖bean,确定能够取得这些已经被确定的bean,如果没有被创建,那么这个createBean会被这些IOC

// getbean时创建这些bean

if (mergedBeanDefinition.getDependsOn() != null) {

for (int i = 0; i < mergedBeanDefinition.getDependsOn().length; i++) {

getBean(mergedBeanDefinition.getDependsOn()[i]);

}

}

........

// 这里是实例化bean对象的地方,注意这个BeanWrapper类,是对bean操作的主要封装类

if (instanceWrapper == null) {

instanceWrapper = createBeanInstance(beanName, mergedBeanDefinition,args);

}

Object bean = instanceWrapper.getWrappedInstance();

......

//这个populate方法,是对已经创建的bean实例进行依赖注入的地方,会使用到在loadBeanDefinition的时候得到的那些propertyValue来对bean进行注入。

if (continueWithPropertyPopulation) {

populateBean(beanName, mergedBeanDefinition, instanceWrapper);

}

//这里完成客户自定义的对bean的一些初始化动作

Object originalBean = bean;

bean = initializeBean(beanName, bean, mergedBeanDefinition);

// Register bean as disposable, and also as dependent on specified "dependsOn"beans.

registerDisposableBeanIfNecessary(beanName, originalBean,mergedBeanDefinition);

return bean;

}

.........

}

 

这就是整个依赖注入的部分处理过程,在这个过程中起主要作用的是WrapperImp ,这个Wrapper不是一

个简单的对bean对象的封装,因为它需要处理在beanDefinition中的信息来迭代的处理依赖注入。

到这里,这是简单的,大概的对IOC和AOP进行了解,入门先到这一点便已经有了大概的印象了

 

分享到:
评论

相关推荐

    SpringSecurity源码

    在学习SpringSecurity源码时,建议从以下几个方面入手: 1. **源码结构分析**:了解主要组件的类结构和它们之间的关系,如`Authentication`、`Authorization`、`FilterChainProxy`等。 2. **关键类的实现**:深入...

    Spring+3.x企业应用开发实战光盘源码(全)

     第8章:介绍了Spring所提供的DAO封装层,这包括Spring DAO的异常体系、数据访问模板等内容。  第9章:介绍了Spring事务管理的工作机制,通过XML、注解等方式进行事务管理配置,同时还讲解了JTA事务配置知识。  ...

    陈开雄 Spring+3.x企业应用开发实战光盘源码.zip

     第8章:介绍了Spring所提供的DAO封装层,这包括Spring DAO的异常体系、数据访问模板等内容。  第9章:介绍了Spring事务管理的工作机制,通过XML、注解等方式进行事务管理配置,同时还讲解了JTA事务配置知识。 ...

    Jboss5源代码-官方-第一部分

    JBoss 5源代码的分析可以从以下几个关键模块入手: 1. **核心服务**:JBoss的核心服务包括事务管理、安全管理、命名与目录服务、JMS消息队列等。这部分源代码展示了如何实现这些基础服务,并与Java EE规范相集成。...

    Spring Security3.1高级详细开发指南

    4. **修改 Spring Security 源代码**:尽管这种方法理论上可行,但实际上并不推荐。它涉及对 Spring Security 的核心组件,如 `InvocationSecurityMetadataSourceService` 和 `UserDetailsService` 进行修改。这种...

    spring第二天.pdf

    可以从BeanDefinition的注册流程、Bean实例创建流程以及依赖注入的实现入手,逐步分析Spring框架的内部工作原理。 通过这些知识点的学习,不仅可以了解Spring框架的基本构造,还能提升解决实际问题的能力,比如优化...

    Spring技术内幕:深入解析Spring架构与设计原理(第2版)

    ### Spring技术内幕:深入解析Spring架构与设计原理(第2版) #### 一、Spring框架简介 Spring框架是由Rod Johnson创建的一个开源项目,它最初是为了简化企业级Java应用程序的开发而设计的。Spring的核心功能包括...

    苏宁易购 源码

    苏宁易购源码是针对苏宁易购电商平台的后端代码库,这通常包含了网站的业务逻辑、数据库交互、用户接口以及服务器端的功能实现。源码分析可以帮助我们深入了解一个大型电商平台的架构设计、数据处理和用户体验优化...

    jsp源码网上订餐系统(struts+spring+hibernate)

    ### jsp源码网上订餐系统(struts+spring+hibernate) #### 一、项目简介 本项目为一个基于JSP技术栈实现的网上订餐系统,主要采用了Struts2、Spring以及Hibernate三大框架进行开发。这不仅体现了对传统JSP技术的一...

    angularJs个人学习笔记及源码

    8. **源码分析**: 压缩包中的源码部分可能包含了一些示例应用,通过阅读和分析这些代码,我们可以更好地理解AngularJS的实际应用和最佳实践。 9. **学习笔记**: 笔记部分可能涵盖了作者在学习过程中的理解、...

    dubbo源码解析

    本文对dubbo源码进行了深入的解析,涵盖了dubbo的架构、核心机制分析、扩展点加载流程、代理机制、远程调用流程、集群和容错处理、监控机制等多个方面。通过阅读和理解这些内容,可以更好地掌握dubbo的内部工作机制...

    lessons-源码.rar

    5. **框架与库的应用**:如果源码中使用了特定的开发框架(如Spring Boot、Django、React等)或第三方库(如jQuery、TensorFlow等),则需要了解这些框架和库的功能和使用方法,以便理解源码如何利用它们来实现功能...

    java权限系统源码

    8. **测试用例**:完整的源码通常会包含单元测试和集成测试,以确保权限系统的正确性和稳定性。 在学习和使用这个源码时,你可以从以下几个角度入手: - 分析源码结构,理解各个类和接口的作用。 - 学习权限验证的...

    买票系统_ticket_车票管理系统_源码.zip.zip

    【标题】中的“买票系统_ticket_车票管理系统_源码.zip.zip”表明这是一个关于车票管理系统的源代码包,经过两次压缩,可能是为了保证数据的安全性和方便传输。车票管理系统是一个典型的信息化解决方案,用于自动化...

    基于springboot的毕设-音乐翻唱与分享平台(源码+配置说明).zip

    SpringBootc8hzm可能是项目的主要源代码包,里面包含启动类、Controller、Service、DAO等层次结构。开发文档.docx可能详细解释了项目的架构设计、技术选型、数据库设计、主要功能的实现原理等内容,是理解项目的重要...

    Java在线协同办公自动化系统源码.zip

    Java在线协同办公自动化系统源码是一套用于构建高效、便捷的企业内部协作平台的代码库,主要面向开发者,尤其是对Java编程语言有深入了解的软件工程师。这套源码提供了完整的功能模块,帮助开发人员快速搭建和定制...

    Java项目源码演示第九期精美风格的轻语音乐网网站.zip

    本项目为"Java项目源码演示第九期精美风格的轻语音乐网网站",主要针对的是Java编程语言,适用于毕业设计或课程设计的学习与实践。这个项目提供了完整的源码,确保用户可以深入理解并进行二次开发。为了更好地理解该...

    Springboot框架.zip

    - `src/main/java`:包含了主要的Java源代码,如主启动类、配置类以及业务逻辑代码。 - `src/main/resources`:存储配置文件、静态资源(如HTML、CSS、JavaScript)和模板文件。 - `pom.xml`或`build.gradle`:构建...

    书城项目代码(全)

    【书城项目代码(全)】是一个基于Java Web技术实现的在线图书商城的完整源代码。这个项目是根据B站上的教程进行开发的,开发者不仅按照视频指导完成了基础功能,还自行扩展实现了视频中未涉及的订单处理功能,充分...

    Java“群买菜”生鲜电商系统源码.zip

    "Java“群买菜”生鲜电商系统源码.zip"是一个包含Java编程语言开发的生鲜电商平台的完整源代码。这个系统可能涵盖了从用户界面到后台管理的一系列功能,旨在为用户提供便捷的在线购买生鲜商品的服务。从文件名...

Global site tag (gtag.js) - Google Analytics