《Spring揭秘》第四章 读书笔记 —— 容器背后的秘密

之前写的草稿居然手残清掉了。。。

spring容器内部是如何实现的呢?在使用的时候,应该都不会怎么考虑spring的内部实现,但是了解一下他背后的秘密也是很有意思的一件事情

spring内部情况

从这幅图片中可以看出来spring容器作为核心,首先以某种方式加载Configuration Metadata 容器会将这些信息解析绑定,装配成系统可用的对象,时刻准备着被调用

spring容器实现的两个阶段

1.容器启动阶段
容器开始启动的时,通过某种方式加载Configuration Metadata,将配置文件中的bean信息解析后,将解析之后的信息组合成相应的BeanDefinition,然后将这些BeanDefinition注册到BeanDefinitionRegistry中。这样启动阶段任务就完成了
初始化阶段
2.Bean实例化阶段
当程序中有请求对象操作或者隐式调用getBean方法的时候,容器会先检查是否已经实例化该对象。如果没有,容器就会根据注册好的BeanDefinition的信息实例化对象,并为其注入依赖;如果对象已经被一些回调接口,也可以根据回调接口装配,装配完毕之后可以直接返回该对象提供使用。

容器启动的时候加点小料
Spring提供了一种叫做BeanFactoryPostProcessor的容器扩展机制。该机制允许我们在容器实例化相应对象之前,对注册到容器的BeanDefinition所保存的信息做相应的修改。这就相当于在容器实现的第一阶段最后加入一道工序,让我们对最终的BeanDefinition做一些额外的操作,比如修改其中bean定义的某些属性,为bean定义增加其他信息等

BeanFactoryProcessor扩展机制中包含了:

  1. PropertyPlaceholderConfigurer
    开发中,我们通常会将一些配置信息不直接放在配置文件,而是将信息用properties文件保存,如果信息有所改变,直接在properties文件中修改,这样既能保证信息的安全性,也能保证修改方便,类似于下面的数据库信息配置
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="driverClassName">
            <value>${jdbc.driver}</value>
        </property>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
    </bean>
    ====================properties文件=======================
    jdbc.url=jdbc:mysql://server/MAIN?useUnicode=true&characterEncoding=ms932&failOverReadOnly=false&
    roundRobinLoadBalance=true
    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.username=your username
    jdbc.password=your password

配置信息中放占位符,引入配置文件,会将对应的属性名称替换掉
2. PropertyOverrideConfigurer
这个扩展用来覆盖替换信息的,也就是说对容器中配置的任何想处理的bean定义的property信息进行覆盖替换

dataSource.maxActive=200
--------------------------------------
# pool-adjustment.properties 11
dataSource.minEvictableIdleTimeMillis=1000
dataSource.maxActive=50
--------------------------------------
<bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
    <property name="location" value="pool-adjustment.properties"/>
</bean>

这里的location对应的配置文件中的信息有一条配置已经被配置过一次,系统引用的值是第二个,因为第一个已经被覆盖掉了(但是我觉得吧,如果这样子的话,直接修改配置文件中的值不就好了 - -!)

  1. CustomEditorConfigurer
    该扩展是辅助性地将后期需要用的信息注入到容器中,对于BeanDefinition没有影响
    spring提供了PropertyEditor,可以完成类型转换,具体的类型转化:
    - StringArrayPropertyEditor 将符合CSV格式的字符串转换成String[]数组的形式
    - ClassEditor 根据String类型的class名称,直接将其转换成相应的Class对象
    - FileEditor 针对java.util.Locale类型
    - PatternEditor 针对java.util.regex.Pattern类型
    也可以自定义PropertyEditor,但是呢我觉得想要类型转换,这种方式貌似也没有在Java中直接转换,不过spring真的强大

Bean的生命周期

bean的一生

  1. Bean的实例化与BeanWrapper
    容器内部实现的过程中,会使用“策略模式”选择使用某种方式实例化,一般会使用反射或者CGLIB动态字节码初始化
    BeanWrapper接口通常在spring内部使用,作用是对某个bean进行“包裹”,然后对“包裹”进行操作,如设置或者是获取对象的某个属性。
  2. 各色的Aware接口
    实例化完成之后,容器会去检查对象是否实现了某些Aware接口,如果有的话又有些相应操作:
    • org.springframework.beans.factory.BeanNameAware 将该对象实例的bean定义对应的beanName设置到当前对象实例
    • org.springframework.beans.factory.BeanClassLoaderAware 将对应加载当前bean的Classloader注入当前对象实例
    • org.springframework.beans.factory.BeanFactoryAware BeanFactory容器会将自身设置到当前对象实例。这样,当前对象实例就拥有了一个BeanFactory容器的引用
  3. BeanPostProcessor
    这个接口和之前看到的BeanFactoryProcessor是不一样的,区分方法也很简单,BeanFactoryProcessor是容器启动时候作用,BeanPostProcessor是在对象实例化阶段作用就很好区别了
    接口声明了两个方法:
    postProcessBeforeInitialization 用来前置处理将要执行的方法
    postProcessAfterInitialization 后置处理将要执行的方法

  4. InitializingBean和init-method
    其中之一可以用来完成初始化工作,用过init-method,在项目启动的时候将数据导入到数据库

<bean id="serverGroupManager" class="com.mhc.fiat.syndingorginfo.task.InitDingDingInfo" init-method="init"/>
  1. DisposableBean与destroy-method
    当对象的调用完成之后,容器将检查singleton类型的bean实例,看其是否实现了org.springframework.beans.factory.DisposableBean接口。或者其对应的bean定义是否通过的destroy-method属性指定了自定义的对象销毁方法。如果是,就会为该实例注册一个用于对象销毁的回调(Callback),以便在这些singleton类型的对象实例销毁之前,执行销毁逻辑。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值