您的位置:首页 > 编程语言 > Java开发

学习《spring 3.x企业应用开发实战》之Spring容器高级主题

2016-07-06 17:06 821 查看
1、Spring容器技术内幕
1.1、内部工作机制
(1)AbstractApplicationContext
AbstractApplicationContext的refresh()方法定义了spring容器在加载配置文件后的各项处理过程。

//①初始化BeanFactory,在这一步里,spring将配置文件信息装入到容器bean定义的注册表BeanDefinitionRegistry中
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();

//②调用工厂后处理器,根据反射机制从BeanDefinitionRegistry中找出所有BeanFactoryPostProcessor类型的Bean,并调用其postProcessBeanFactory接口方法
invokeBeanFactoryPostProcessors(beanFactory)

//③注册Bean后处理器,根据反射机制从BeanDefinitionRegistry中找出所有BeanPostProcessor类型的Bean,并将它们注册到容器Bean后处理器的注册表中
registerBeanPostProcessors(beanFactory)

//④初始化消息源,初始化容器的国际化信息资源
initMessageSource()

//⑤初始化应用上下文事件广播器
initApplicationEventMulticaster()

//⑥初始化其他特殊Bean,由子类具体实现
onRefresh()

//⑦注册事件监听器
registerListeners()

//⑧初始化所有单实例的Bean,懒汉模式的Bean除外
finishBeanFactoryInitialization(beanFactory)

//⑨完成刷新并发布容器刷新事件
finishRefresh()
注:jdk的事件监听器类---------EventObject

(2)IoC的流水线



工厂后处理器主要完成2项工作:
对使用到占位符的<bean/>标签进行解析
对BeanDefinitionRegistery中的BeanDefinition进行扫描,通过java反射机制找出所有属性编辑器的Bean(实现java.beans.PropertyEditor接口的Bean),并自动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistery)

(3)Spring的高明之处在于,它使用众多接口描绘出了所有装置的蓝图,构建好Spring的骨架,继而通过继承体系层层推演,不断丰富。
所以查看Spring框架的源码时,有2条清晰的脉络:

接口层描述了容器的重要组件及组件间的协作关系;
继承体系逐步实现组件的各项功能。

1.2、BeanDefinition
(1)BeanDefinition是<bean/>元素在容器中的内部表示,BeanDefinition接口的继承结构如图:



①RootBeanDefinition是最常用的实现类,它对应一般性的<bean/>元素,没有子元素的<bean/>就对应RootBeanDefinition。
②BeanDefinition被Spring容器注册到BeanDefinitionRegistry中,BeanDefinitionRegistry就像是Spring配置信息的内存数据库,后续操作直接从BeanDefinitionRegistry中读取配置信息。

(2)创建最终的BeanDefiniton主要包含2个步骤:

利用BeanDefinitionReader对Resource进行读取;
利用容器中注册的BeanFactoryPostProcessor对半成品BeanDefinition进行加工,以处理占位符的值,

1.3、InstantiationStrategy
(1)Spring之所以将实例化Bean的工作采用策略接口来描述,是为了方便采用不同的实例化策略,如通过cglib类库为Bean动态创建子类再实例化。
InstantiationStrategy的类继承结构如图:



①SimpleInstantiationStrategy是最常用的实现类,该策略利用Bean的构造方法或者工厂方法创建Bnan实例
②CglibSubclassingInstantiationStrategy扩展了SimpleInstantiationStrategy,为需要进行方法注入的Bean提供了支持,它使用cglib为Bean动态生成子类,在子类中实现方法注入的逻辑。

(2)InstantiationStrategy只负责实例化Bean的工作,相当于java中的new功能,它并不会参与Bean属性的设置,属性的设置需要BeanWrapper来完成。

1.4、BeanWrapper
(1)BeanWrapper相当于一个代理器,spring通过BeanWrapper设置Bean的属性值,BeanWrapper类的继承结构如图:



①BeanWrapper有2个顶级接口,分别是PropertyAccessor和PropertyEditorRegistry,

PropertyAccessor接口定义了各种访问设置Bean属性的方法;
PropertyEditorRegistry是属性编辑器的注册表。

②BeanWrapper的实现类BeanWrapperImpl从BeanDefinitionRegistry获取到BeanDefinition,再从BeanDefinition中获得Bean的属性信息,并利用BeanUtils通过反射对Bean进行操作。

2、属性编辑器
在Spring配置文件里,我们往往通过字面值为Bean的属性设置值,属性编辑器的作用就是将这些字面值转换为相应的double或int型值,所以属性编辑器就是一个类型转换器。

2.1、JavaBean的编辑器
PropertyEditor是JavaBean规范定义的接口。

2.2、Spring默认编辑器
Spring的属性编辑器并非传统的IDE编辑器JavaBean,同时Spring还支持自定义属性编辑器

3、使用外部属性文件
(1)在进行数据源或邮件服务器等资源时,用户可以直接在Spring配置文件中配置用户名、密码。但更好的一种做法是将这些配置信息独立到一个外部属性文件中,并在spring配置文件中通过Spel表达式,形如${xxxx}等占位符引用属性文件中的属性项。
(2)Spring为我们提供了一个PropertyPlaceholderConfigurer,它能够使Bean在配置时引用外部属性文件,PropertyPlaceholderConfigurer实现了
BeanFactoeyPostProcessor接口,所以它也是一个工厂后处理器。xml中配置方式如下:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:important.properties</value>
            <value>classpath:webjsf.properties</value>
        </list>
    </property>
</bean>
(3)spring提供了一个更优雅的方式,使用
<context:property-placeholder    location="classpath:....................">
(4)在基于注解配置中引用属性
使用@Value("${xxxxx}")引用属性文件中的值。
(5)有时候,用户名、密码等信息需要加密处理,我们可以扩展PropertyPlaceholderConfigurer类,将用户名和密码使用DES加密的密文填入属性文件。并覆盖convertProperty方法,对用户名和密码进行解密转换。
注:使用自定义的解析类时,就无法使用<context:property-placeholder/>了,必须通过传统的方式,配置PropertyPlaceholderConfigurer的扩展类。
(6)Spring允许在属性文件中使用Spel表达式,实现属性之间的相互引用,如果一个属性值太长写不下,可以通过在航后添加“\”将属性值划分为多行。

4、引用Bean的属性值
spring通过Spel表达式(#{........})在基于注解或者XML的配置中引用其他Bean的属性值

5、容器事件
Spring的ApplicationContext能够发布事件并且允许注册相应的事件监听器,java通过java.util.EventObject类和java.util.EventListener接口描述事件和监听器,某个组件或框架要想建立自己的事件监听机制,一般都通过扩展EventObject和EventListener来实现。
在事件体系中,除了事件和监听器以外,还有另外3个重要的概念:

事件源:事件的产生者,任何一个EventObject都必须有一个事件源;
事件监听器注册表:一个事件监听器注册到组件或者框架中,其实就是保存在监听器注册表里,当组件和框架中的事件源产生事件时,就会将事件通知这些监听器;
事件广播器:它是事件和时间监听器的沟通桥梁,负责把事件通知给事件监听器。

5.1、Spring事件类结构
(1)spring事件类结构如图:



注:ApplicationEvent只有一个构造函数,ApplicationEvent(Object    source),通过source指定事件源。

(2)事件监听器接口类图:



(3)事件广播器类图:



5.2、解构Spring事件体系的具体实现
(1)Spring在ApplicationContext接口的抽象实现类AbstractApplicationContext中完成了事件体系的搭建
AbstractApplicationContext有一个事件广播器applicationEventMulticaster成员变量,该变量提供了容器监听器的注册表。

(2)用户可以自定义事件广播器,如果没有配置自定义广播器,spring将默认使用SimpleApplicationEventMulticaster广播器。
(3)初始化事件广播器之后,spring通过反射机制从BeanDefinitionRegistry中找出所有实现ApplicationListener接口的Bean,将它们添加到事件广播器的监听器注册表中。
(4)要使自定义的事件广播器拥有发布事件的能力,必须实现ApplicationContextAware接口,ApplicationContextAware接口的publishEvent方法可以发布事件,该方法的参数就是事件。
(5)自定义spring事件监听机制的过程分为3步:

定义一个时间Event;
定义一个监听器Listener;
定义一个事件广播器,实现ApplicationContextAware接口,可以获得ApplicationContext事件源,产生一个事件Event,调用事件源的发布方法publishEvent。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring