`
graykeel
  • 浏览: 15710 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

spring的bean的创建

阅读更多

spring作为一个轻量级J2EE应用框架,已经被广大的开发人员认为是最优秀的框架之一,得到了广泛的应用,其基于IOC的设计理念使得开发人员可以不必过多的关注框架层面的实现,可以更加专注于业务逻辑的实现。对于spring的分析文章已有很多,本人就将根据这就的理解来一步一步的分析spring的源代码,其中有不正确的地方还请大家拍砖指出,初次编写,有不好的地方请大家多多指正。
在spring的模块图如下:

spring一共包含7大模块,其中Spring Core模块是整个框架的最基础的部分,提供了IOC基础。Spring包的总体架构图如下:


从以上spring包的命名上看我们可以看出spring对j2ee提供了相当完善的支持,基本上是一个一站式服务的解决方案。
其中Core,beans包和context包是Spring Ioc的基础,没有他们也就没有了spring的上层应用如AOP,ORM,DAO等。在spring中,bean是最基本的元素,属于基础设施。而bean的创建获取操作均在beans包中完成。而bean是如何创建的呢?众所周知,BeanFactory是IoC容器的核心接口,它的职责包括:实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。进入BeanFactory中我们可以看到其提供的接口功能主要有:
//根据bean名字或者id获取bean实例对象
Object getBean(String name) throws BeansException;
//这里根据bean的名字或者id和Class类型来得到bean实例,
Object getBean(String name, Class requiredType) throws BeansException;
//根据bean的名称或者id和相应的参数获取bean的实例,此处对于作用域为singleton的会报错
Object getBean(String name, Object[] args) throws BeansException;
//检查容器中是否含有该名称或者id的bean
boolean containsBean(String name);
//根据bean的名称或者id判断该bean的作用域是否为singleton
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//根据bean的名称或者id判断该bean的作用域是否为prototype
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
//根据所给的bean名称或者id和类类型来获取相应的bean实例
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
//根据所给的bean名称或者id获取该bean的类类型
Class getType(String name) throws NoSuchBeanDefinitionException;
//根据所给的bean的名称来获取或者id来获取该bean的别名
String[] getAliases(String name);


从上图中我们可以看到BeanFactory在当前包中有两个子类及一个实现类,即接口HierarchicalBeanFactory及ListableBeanFactory和实现类SimpleJndiBeanFactory,且在config包中有一个子类AutowireCapableBeanFactory,关于SimpleJndiBeanFactory(由spring2.5以后添加)我们暂且不关注其作用,先来看看剩下的三个接口:

接口名
作用
HierarchicalBeanFactory
此方法提供了两个接口,主要功能有判断当前BeanFactory中是否含有指定名称的bean、获取父BeanFactory
ListableBeanFactory
提供对容器内的bean的枚举与遍历功能:
查找是否有指定名称bean的定义
获取容器内bean的数量及所有bean的名称
根据指定类型获取bean的集合

AutowireCapableBeanFactory
提供自动装配的功能,即bean的创建等功能均由该接口实现,如createBean,autowireBean,configureBean等方法
从以上接口功能的设计及继承体系上看我们可以发现spring有着良好的接口设计,很好的体现了接口分级,不同级别的接口面对的对象不同,所需要提供的功能也不尽相同,和单一职责原则,并且接口分工明确,通过继承来完善和扩展主要接口的功能。其中BeanFactory属于spring的顶级接口,主要提供了与bean的查找的相关方法。其他继承自BeanFactory的接口,并从不同的方面完善了BeanFactory的功能。
就让我们先来看看bean是如何创建出来的?
对于接口AutowireCapableBeanFactory来说有一个子继承接口ConfigurableListableBeanFactory和一个抽象实现类AbstractAutowireCapableBeanFactory,相对于两个的子类来说,其最终的实现均为XmlBeanFactory。
AbstractAutowireCapableBeanFactory的依赖关系图


由上图我们可以看到AbstractAutowireCapableBeanFactory还继承了AbstractBeanFactory,并且在这个类中我们可以看到
private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();
我们进入CglibSubclassingInstantiationStrategy类中可以看到注释中有一段话“BeanFactory的默认类初始化策略”,其继承自SimpleInstantiationStrategy方法,我们可以在CglibSubclassingInstantiationStrategy类的注释中看到如果我们在应用中启用了CGLIB之后则spring将采用CGLIB来动态生成类的方式来实现方法的动态代理以及类的注入,当然BeanFactory容器仍然能够在CGLB没有使用的情况下正常工作。即如果在classpath写明了CGLIB运行库时将会采用CGLIB的动态代理,否则将采用JDK的默认动态代理。
由此可见如果在声明了CGLIB的情况下spring的bean创建默认是采用CGLIB的方式进行类的生成的。
AbstractAutowireCapableBeanFactory实现了AutowireCapableBeanFactory的接口的很多方法,在这里我们主要看spring的bean的创建过程,所以就先看看关于createBean的方法:
//根据给出的类来创建bean的实例,该方法创建的是一个全新的bean实例
Object createBean(Class beanClass) throws BeansException;
//根据指定装载策略和类创建一个该类的实例,装载策略包括AUTOWIRE_NO,AUTOWIRE_BY_NAME,AUTOWIRE_BY_TYPE,AUTOWIRE_CONSTRUCTOR,AUTOWIRE_AUTODETECT
Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
关于两个方法的实现如下:
public Object createBean(Class beanClass) throws BeansException {
// Use prototype bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass);
bd.setScope(SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}

public Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException {
// Use non-singleton bean definition, to avoid registering bean as dependent bean.
RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
return createBean(beanClass.getName(), bd, null);
}
两个实现类的唯一区别在于RootBeanDefinition bd = new RootBeanDefinition(beanClass);和RootBeanDefinition bd = new RootBeanDefinition(beanClass, autowireMode, dependencyCheck);上面。其中RootBeanDefinition继承自AbstractBeanDefiniton,而从下图我们可以看出:

RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition均继承了AbstractBeanDefiniton,其中BeanDefinition是配置文件<bean>元素标签在容器中内部表示形式。<bean>元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的beanClass、scope、lazyInit属性,BeanDefinition和<bean>中的属性是一一对应的。其中RootBeanDefinition是最常用的实现类,它对应一般性的<bean>元素标签,GenericBeanDefinition是自2.5以后新加入的bean文件配置属性定义类,是一站式服务类。在配置文件中可以定义父<bean>和子<bean>,父<bean>用RootBeanDefinition表示,而子<bean>用ChildBeanDefiniton表示,而没有父<bean>的<bean>就使用RootBeanDefinition表示。AbstractBeanDefinition对两者共同的类信息进行抽象。
Spring通过BeanDefinition将配置文件中的<bean>配置信息转换为容器的内部表示,并将这些BeanDefiniton注册到BeanDefinitonRegistry中。Spring容器的BeanDefinitionRegistry就像是Spring配置信息的内存数据库,主要是以map的形式保存,后续操作直接从BeanDefinitionRegistry中读取配置信息。一般情况下,BeanDefinition只在容器启动时加载并解析,除非容器刷新或重启,这些信息不会发生变化,当然如果用户有特殊的需求,也可以通过编程的方式在运行期调整BeanDefinition的定义。
创建最终的BeanDefinition主要包括两个步骤:
1)利用BeanDefinitionReader对配置信息Resource进行读取,通过XML解析器解析配置信息的DOM对象,简单地为每个<bean>生成对应的BeanDefinition对象。但是这里生成的BeanDefinition可能是半成品,因为在配置文件中,我们可能通过占位符变量引用外部属性文件的属性,这些占位符变量在这一步还没有被解析出来。
2)利用容器中注册的BeanFactoryPostProcessor对半成品的BeanDefinition进行加工处理,将以占位符表示的配置解析为最终的实际值,这样半成品的BeanDefinition就为成品的BeanDefinition。

ConfigurableListableBeanFactory介绍


该接口的主要提供了一些分析和更改BeanDefinition的方法以及单例bean的预创建功能。从该类的继承关系上看我们发觉该接口同时继承了ListableBeanFactory, AutowireCapableBeanFactory以及ConfigurableBeanFactory接口,而HierarchicalBeanFactory则继承了HierarchicalBeanFactory和 SingletonBeanRegistry接口,由此可见一个ConfigurableListableBeanFactory就拥有了所有的这些接口功能,而其为什么还要分出这么多的接口类出来呢!?这就是接口的分级设计及单一功能体现,不同的接口提供不同的功能,并通过接口的继承来完善和扩展功能。
该接口具有一个实现类DefaultListableBeanFactory,该类通过一系列的继承实现了这些接口的所有方法,至此有关spring bean的创建,定义以及bean间关系的建立等均已完成,但是对于资源的读取并没有实现,通过下图我们可以看出

DefaultListableBeanFactory还有一个子类XmlBeanFactory,XmlBeanFactory是BeanFactory的一个常用实现,
进入该子类可以看出里面仅有两个构造方法:
//根据给出的资源创建XmlBeanFactory
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//根据给出的资源以及父 BeanFactory创建XmlBeanFactory
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
现在我们可以总结出整个bean的生成过程了:
1:生成xml格式的配置文件
2:通过ResourceLoader将配置文件读入
3:通过BeanDefinitionReader将配置信息转换程BeanDefinition
4:在通过BeanFactory根据BeanDefinition信息创建bean实例
5:将bean实例放入SingletonBeanRegistry中以供使用
现在我们来看看bean的产生过程中这些接口,类的功能的划分,继承的层级可以发现spring对每一个功能都进行了很好的抽象,并进行了良好的接口功能划分,如BeanFactory接口,及其子类接口,虽然在最终我们看到只有一个类即DefaultListableBeanFactory通过继承实现了这些所有的接口。但是从这一点上我们可以看出spring将类的功能划分的非常细致,并不是讲所有的功能通过一个接口来体现,而是一步一步的分层级来实现这些功能,尽可能高度的抽象。

 

  • 大小: 103.9 KB
  • 大小: 12.3 KB
  • 大小: 261.7 KB
  • 大小: 105.9 KB
  • 大小: 78.2 KB
  • 大小: 62.5 KB
  • 大小: 4.8 KB
分享到:
评论

相关推荐

    Spring Bean创建初始化流程.docx

    以下是对Spring Bean创建初始化流程的详细解释: 1. **初始化ApplicationContext**: 开始时,通过`AnnotationConfigApplicationContext`类创建一个上下文实例,通常传入一个或多个配置类(`annotatedClasses`),...

    spring bean创建

    spring bean创建过程

    spring bean的生命周期

    - **XML配置**:在传统的Spring应用中,Bean的定义通常写在XML配置文件中,如`springbean-xml`中的配置。 - **注解配置**:使用`@Component`,`@Service`,`@Repository`和`@Controller`注解标记类,配合`@...

    spring bean XML配置入门

    在Spring中,一个Bean通常代表应用中的一个对象,这些对象由Spring容器创建、管理并提供给其他组件使用。Spring容器通过XML配置文件或注解来定义Bean及其相互关系。 3. **XML配置文件**: "spring-beans"是Spring...

    创建SpringBean配置工具类

    创建SpringBean配置工具类(安全)如: &lt;bean id=... scope="prototype"&gt;&lt;/bean&gt;

    Spring Bean重复执行两次(实例被构造两次)问题分析

    在Spring容器初始化时,它会根据配置加载Bean的定义,并根据需要创建Bean实例。Bean的生命周期大致分为以下几个阶段:构造、初始化、正常使用、销毁。如果一个Bean被创建了两次,那么可能是在构造或初始化阶段出现了...

    spring创建bean简单示例

    本示例将深入探讨如何在Spring中创建和管理Bean。首先,我们需要理解Spring的IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)原理,这两个概念是Spring框架的核心。 **控制反转(IoC...

    普元eos-springbean开发

    - **SpringBean开发**:了解如何在EOS平台上创建和配置SpringBean。 - **SpringBean调用**:掌握如何在其他组件中调用已定义好的SpringBean。 - **SpringBean调试**:学会使用EOS提供的调试工具来定位和解决问题...

    实例化Spring bean的两种工厂方法

    本篇将详细探讨两种工厂方法——实例工厂方法和静态工厂方法,用于创建Spring Bean。 首先,我们要理解Spring Bean的概念。Spring Bean是Spring IoC容器管理的对象,这些对象的生命周期、依赖关系以及初始化行为由...

    springBean加载过程源码解析文档,附有代码类名和行数

    Spring Bean 加载过程源码解析文档 Spring Bean 加载过程是 Spring 框架中最核心的部分之一,涉及到 ApplicationContext 的初始化、Bean 的加载和注册等过程。在 Spring Boot 应用程序中,SpringApplication 负责...

    spring bean life cycle

    在Spring框架中,Bean生命周期是核心概念之一,它涉及到Bean的创建、初始化、使用和销毁等阶段。了解和掌握Bean生命周期对于开发高质量的Spring应用至关重要。以下是对Spring Bean生命周期的详细解析。 首先,Bean...

    spring bean 属性总结

    这是Spring创建Bean实例的基础。 - **id属性**:是Bean在BeanFactory中的唯一标识符,用于通过BeanFactory获取Bean实例。例如,`&lt;bean id="myBean" class="com.example.MyClass"&gt;`。 - **name属性**:类似于`id`...

    Spring Bean 加载顺序 .

    在Spring框架中,Bean的加载顺序是理解Spring IoC(Inversion of Control,控制反转)容器工作原理的关键部分。这个过程涉及到Bean定义的解析、实例化、初始化等多个步骤。让我们详细探讨Spring Bean加载顺序的各个...

    粗略实现spring创建bean

    - 切面自动代理:Spring能够自动为Bean创建代理,以便在方法调用前后执行额外逻辑。 6. Spring Bean 的装配 - 自动装配:通过`@Autowired`注解自动寻找匹配类型的Bean进行装配。 - 配置文件指定:在XML配置文件...

    spring bean的生命周期测试代码

    在Spring框架中,Bean的生命周期管理是其核心特性之一,它允许开发者控制Bean从创建到销毁的整个过程。本资源提供了在Spring 4.2环境下关于Bean生命周期的测试代码,帮助我们深入理解这一关键概念。 首先,让我们...

    详解Spring 中如何控制2个bean中的初始化顺序

    Spring 中的 DependsOn 注解可以保证被依赖的 bean 先于当前 bean 被容器创建。例如,在 B 上加上注解 @DependsOn({"a"}),这样可以保证 A 先于 B 被初始化。 需要注意的是,bean 属性的注入是在初始化方法调用之前...

    Spring bean 管理

    在Spring中,Bean的管理包含多个方面:创建Bean实例、配置Bean属性、控制Bean的生命周期以及Bean作用域的定义。接下来将详细解释这些知识点。 1. Spring的工厂类: Spring通过工厂模式设计了一系列工厂类来创建对象...

    Spring Bean简单应用实例

    1. **Bean定义**:Bean定义是Spring容器如何创建和管理Bean的描述。它可以是一个XML配置文件中的元素,或者使用Java配置类和注解。例如: ```xml &lt;bean id="myBean" class="com.example.MyClass"&gt; &lt;!-- 可能还有...

    Spring的Bean配置

    在Spring中,Bean是应用中的对象,它们由Spring IoC容器负责创建、管理和装配。Bean配置是定义这些对象如何被创建和如何相互关联的过程。 **IoC(Inversion of Control)和DI(Dependency Injection)**: IoC是...

    Spring 源码(14)Spring Bean 的创建过程(5).doc

    在Spring框架中,Bean的创建过程是一个复杂而精细的机制,涉及到多个步骤和接口的交互。在本篇中,我们将深入探讨Spring Bean的第五种创建方式,即通过反射进行创建,特别是利用`...

Global site tag (gtag.js) - Google Analytics