秋天里的春天-spring笔记(二):IoC

一、             IoC核心

springIoC容器核心为BeanFactory接口,该接口的最常用实现是XmlBeanFactory类,该类使用xml配置文件来初始化一个BeanFactory实例。

ApplicationContext是对BeanFactory接口的扩展,在大多数的应用中,使用ApplicationContext的优先级要高于BeanFactory,两者对比如下:

特性

BeanFactory

ApplicationContext

Bean 实例化/装配

Yes

Yes

自动 BeanPostProcessor 注册

No

Yes

自动 BeanFactoryPostProcessor 注册

No

Yes

便捷的 MessageSource 访问( i18n)

No

Yes

ApplicationEvent 发送

No

Yes

 

l  ApplicationContexti18n

ApplicationContext接口扩展了MessageSource接口。

String getMessage(String code, Object[] args, String default, Locale loc)

String getMessage(String code, Object[] args, Locale loc)

String getMessage(MessageSourceResolvable resolvable, Locale locale)

 

当一个ApplicationContext被加载时,它会自动在context中查找已定义为MessageSource类型的bean。此bean的名称须为messageSource。如果找到,那么所有对上述方法的调用将被委托给该bean。否则ApplicationContext会在其父类中查找是否含有同名的bean。如果有,就把它作为MessageSource。如果它最终没有找到任何的消息源,一个空的StaticMessageSource将会被实例化,使它能够接受上述方法的调用。

 

Spring目前提供了两个MessageSource的实现:ResourceBundleMessageSourceStaticMessageSource

<beans>

  <bean id="messageSource"

        class="org.springframework.context.support.ResourceBundleMessageSource">

    <property name="basenames">

      <list>

        <value>format</value>

        <value>exceptions</value>

        <value>windows</value>

      </list>

    </property>

  </bean>

</beans>

这段配置假定在你的classpath中有三个资源文件

 

l  ApplicationContext的事件

ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口来提供的。如果在上下文中部署一个实现了ApplicationListener接口的bean,那么每当一个ApplicationEvent发布到ApplicationContext时,这个bean就得到通知。

 

内置事件

ContextRefreshedEvent

ApplicationContext初始化或刷新时发送的事件

ContextStartedEvent

ApplicationContext启动时发送的事件,使用ConfigurableApplicationContext接口的start()方法。

ContextStoppedEvent

当使用ConfigurableApplicationContext接口的stop() 方法使ApplicationContext停止时候发送的事件

ContextClosedEvent

当使用ConfigurableApplicationContext接口close() 方法使ApplicationContext 关闭时候发送的事件

RequestHandledEvent

web特性的事件通告所有的bean有一个http request(将在request结束后才会发送)。注意这种事件只兼容于使用SpringDispatcherServlet兼容的web应用

 

只要在ApplicationContext调用publishEvent()方法可以很方便的实现自定义事件,将一个实现了ApplicationEvent的自定义事件类作为参数就可以了。事件监听器同步的接收事件。这意味着publishEvent()方法将被阻塞,直到所有的监听器都处理完事件(可以通过一个ApplicationEventMulticaster的实现提供可选的事件发送策略)。此外,如果事务context可用,监听器会接收到一含有发送者事务context的事件。

 

l  资源管理

SpringResource接口负责管理资源。内置的资源实现有:

UrlResource UrlResource 封装了java.net.URL

 

ClassPathResource classpath 这个类标识从classpath获得的资源。它会使用线程context的类加载器(class loader)、给定的类加载器或者用来载入资源的给定类

 

FileSystemResource 这是为处理 java.io.File 而准备的Resource实现。它既可以作为File提供,也可以作为URL

 

ServletContextResource 这是为 ServletContext 资源提供的 Resource 实现,它负责解析相关web应用根目录中的相对路径。 它始终支持以流和URL的方式访问。 但是只有当web应用包被解开并且资源在文件系统的物理路径上时,才允许以 java.io.File 方式访问

 

InputStreamResource 这是为给定的 InputStream 而准备的 Resource 实现。它只有在没有其它合适的 Resource 实现时才使用

 

ByteArrayResource 这是为给定的byte数组准备的 Resource 实现,它在从任何给定的byte数组读取内容时很有用

 

下面的表格概述了 String Resource 的转换规则

classpath:

classpath:com/myapp/config.xml

classpath中加载

file:

file:/data/config.xml

作为 URL 从文件系统中加载

http:

http://myserver/logo.png

作为 URL 加载

(none)

/data/config.xml

根据 ApplicationContext 进行判断

 

Application实现了ResourceLoader接口,可以用来管理ResourceResourceLoaderAware接口用于感知容器的Resource管理,可以稍稍降低自定义资源管理器对spring的依赖。在配置文件中可以按照如下的格式配置资源

<bean id="myBean" class="...">

  <property name="template" value="some/resource/path/myTemplate.txt"/>

</bean>

 

二、             xml配置的方法

1.使用ApplicationContext的时候可以把文件路径作为字符串数组传递给ApplicationContext实现类的构造函数。

2.<beans>中所有<bean>配置节的前面加<import>标签,如:<import resource="services.xml"/>

 

Import标签

名称

描述

resource

字符串

需要引入的spring配置文件(xml格式)的相对位置。

 

三、             配置bean

当采用XML描述配置元数据时,将通过<bean/>元素来配置一个类,实例化的方式有三种:

l  class属性来指定实例化对象的类型

l  静态工厂方法创建bean时,除了需要指定class属性外,还需要通过factory-method属性来指定创建bean实例的工厂方法。

l  使用实例工厂方法实例化,使用factory-bean属性指定实例工厂的名称,通过factory-method属性来指定创建bean实例的工厂方法

 

bean标签

名称

描述

abstract

布尔型

标识该bean配置是否为抽象配置。

autowire

default

no

byName

byType

constructor

autodetect

指定bean的自动装配属性

byName-根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配。例如,在bean定义中将autowire设置为by name,而该bean包含master属性(同时提供setMaster(..)方法),Spring就会查找名为masterbean定义,并用它来装配给master属性。

byType-如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,那么将会抛出异常,并指出不能使用byType方式进行自动装配。若没有找到相匹配的bean,则什么事都不发生,属性也不会被设置。如果你不希望这样,那么可以通过设置dependency-check="objects"Spring抛出异常。

constructor-与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。

autodetect-通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式。

autowire-candidate

布尔型

autowire-candidate属性被设为false时,容器在查找自动装配对象时将不考虑该bean

class

字符串

bean对应的类名称。

对于一个静态的内部类,名字需要采用二进制的写法。如在com.example包下有一个叫Foo的类,而Foo类有一个静态的内部类叫Bar,那么在bean中这样写:com.example.Foo$Bar

dependency-check

default

none

simple

objects

all

设置bean的依赖检查方式

none-没有依赖检查,如果bean的属性没有值的话可以不用设置。

simple-对于原始类型及集合(除协作者外的一切东西)执行依赖检查

object-仅对协作者执行依赖检查

all-对协作者,原始类型及集合执行依赖检查

depends-on

字符串

该属性可以用于当前bean初始化之前显式地强制一个或多个bean被初始化(多个bean名字用分隔符进行分隔,分隔符可以是逗号、空格及分号等)。该属性同时也用来指定相应的销毁时的依赖(该依赖只针对singletonbean)。depends-on属性中指定的依赖bean会在相关bean销毁之前被销毁,从而可以让用户控制销毁顺序。

destroy-method

字符串

销毁回调方法名称。

factory-bean

字符串

使用实例工厂方法实例化bean时,class属性必须为空,而factory-bean属性必须指定为当前(或其祖先)容器中包含工厂方法的bean的名称,而该工厂bean的工厂方法本身必须通过factory-method属性来设定。

factory-method

字符串

当采用静态工厂方法创建bean时,除了需要指定class 属性外,还需要通过该属性来指定创建bean实例的工厂方法。

id

字符串

bean的唯一标识

init-method

字符串

初始化回调方法名称。

lazy-init

default

true

false

ApplicationContext实现的默认行为就是在启动时将所有singleton bean提前进行实例化。lazy-init属性来控制bean是否能提前初始化

name

字符串

bean的别名,可以用逗号分割指定多个别名

parent

字符串

指出该bean配置的父配置

scope

字符串

prototype-非单例

singleton-单例,缺省值

request-在一次HTTP请求中,一个bean定义对应一个实例;即每次HTTP请求将会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于webSpring ApplicationContext情形下有效。

session-在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于webSpring ApplicationContext情形下有效。

global session-在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于webSpring ApplicationContext情形下有效。

 

四、             bean的别名

在对bean进行定义时,除了使用id属性来指定名称之外,为了提供多个名称,需要通过name属性来加以指定 。而所有的这些名称都指向同一个bean。也可以通过独立的alias标签来指定别名。

 

alias标签

名称

描述

name

字符串

该别名引用的bean名称

alias

字符串

别名

 

五、             构造器注入

通过<bean>元素下的<constructor-arg>来完成。

 

constructor-arg标签

名称

描述

index

字符串

显式指定构造参数的索引。用于构造器注入过程中因重载造成的问题。索引从0开始

ref

字符串

<constructor-arg ref="benaName">

是如下形式的简写:

<constructor-arg>

  <ref bean="benaName" />

</constructor-arg>

type

字符串

显式指定那些简单类型的构造参数的类型。用于构造器注入过程中因重载造成的问题。

value

字符串

<constructor-arg value="stringValue">

是如下形式的简写:

<constructor-arg>

  <value > stringValue</value>

</constructor-arg>

 

六、             Setter注入

通过调用无参构造器或无参static工厂方法实例化bean之后,调用该beansetter方法,即可实现基于setterDI

 

property标签

名称

描述

name

字符串

属性的名称

ref

字符串

参见constructor-arg标签

value

字符串

参见constructor-arg标签

 

七、             依赖配置

<value>元素通过字符串来指定属性或构造器参数的值,PropertyEditor将用于把字符串从java.lang.String类型转化为实际的属性或参数类型。

 

value标签

名称

描述

type

字符串

指定该值的类型

 

<idref>元素用来将容器内其它beanid传给<constructor-arg/> <property/>元素,同时提供错误验证功能。其属性可以参考<ref>元素。<ref>元素用来将bean中指定属性的值设置为对容器中的另外一个bean的引用。共有三种形式

 

ref元素

名称

描述

bean

字符串

可以引用同一容器或父容器内的任何bean(无论是否在同一XML文件中)。XML 'bean'元素的值既可以是指定beanid值也可以是其name值。

local

字符串

它可以利用XML解析器来验证所引用的bean是否存在同一文件中。local属性值必须是目标beanid属性值

parent

字符串

引用当前容器的父容器中的beanparent属性值既可以是目标beanid值,也可以是name属性值。而且目标bean必须在当前容器的父容器中。

 

内部bean

所谓的内部beaninner bean)是指在一个bean<property/> <constructor-arg/>元素中使用<bean/>元素定义的bean。内部bean定义不需要有idname属性,即使指定id name属性值也将会被容器忽略。内部bean中的scope标记及idname属性将被忽略。内部bean总是匿名的且它们总是prototype模式的。同时将内部bean注入到包含该内部bean之外的bean是不可能的。

 

list标签

名称

描述

merge

default

true

false

是否在bean的继承关系中进行集合的合并。父子集合元素合并后的值就是子集合中的最终结果,而且子集合中的元素值将覆盖父集全中对应的值。不同的集合类型是不能合并。merge属性必须在继承的子bean中定义

value-type

字符串

指定list中元素的类型

 

set标签

名称

描述

merge

default

true

false

是否在bean的继承关系中进行集合的合并。父子集合元素合并后的值就是子集合中的最终结果,而且子集合中的元素值将覆盖父集全中对应的值。不同的集合类型是不能合并。merge属性必须在继承的子bean中定义

value-type

字符串

指定set中元素的类型

 

map标签

名称

描述

merge

default

true

false

是否在bean的继承关系中进行集合的合并。父子集合元素合并后的值就是子集合中的最终结果,而且子集合中的元素值将覆盖父集全中对应的值。不同的集合类型是不能合并。merge属性必须在继承的子bean中定义

value-type

字符串

指定map中值的类型

key-type

字符串

指定map中键的类型

 

entry标签-只能出现在<map>

名称

描述

key

字符串

该键值对的键名称

key-ref

字符串

该键值对的键引用,相当于<ref bean=””/>

value

字符串

该键值对的值

value-ref

字符串

该键值对的值引用,相当于<ref bean=””/>

 

props标签

名称

描述

merge

default

true

false

是否在bean的继承关系中进行集合的合并。父子集合元素合并后的值就是子集合中的最终结果,而且子集合中的元素值将覆盖父集全中对应的值。不同的集合类型是不能合并。merge属性必须在继承的子bean中定义

 

prop标签-只能出现在props标签内

名称

描述

key

字符串

键名称

 

null标签-传递null值。

 

八、             方法注入

是指在类中定义抽象方法,在容器中配置使spring实现该抽象方法的技术。主要用来解决单例bean返回非单例bean的情况。

抽象方法应该如下:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

配置文件如下:

<bean id="commandManager" class="fiona.apple.CommandManager">

  <lookup-method name="theMethodName" bean="command"/>

</bean>

注意,lookup-method标签的name属性应和抽象方法名称一致,而bean属性指向的应该是该抽象方法返回类型在容器中的bean引用。

 

lookup-method标签

名称

描述

name

字符串

注入的方法名称

bean

字符串

注入的返回类型。

 

九、             方法替换

允许用一个实现了MethodReplacer接口的bean去替换其他bean上的方法实现。

 

replaced-method标签

名称

描述

name

字符串

要替换的方法的名称

replacer

字符串

实现了MethodReplacer接口的bean

 

arg-type标签-只能出现在replaced-method标签内,用来指定替换的方法的参数(重载情况)

名称

描述

match

字符串

 

 

十、             bean的作用域

在使用requestsession以及global session三个web相关的bean作用域的时候,如果不是使用spring mvc,需要在web.xml做额外的配置:

org.springframework.web.context.request.RequestContextListener Servlet2.4或更高版本

org.springframework.web.filter.RequestContextFilterServlet2.4以前的版本

 

RequestContextListenerRequestContextFilter两个类做的都是同样的工作: HTTP request对象绑定到为该请求提供服务的Thread 这使得具有requestsession作用域的bean能够在后面的调用链中被访问到。

如果需要在上述三个作用域的bean中实现DI(与普通作用域的bean),需要在web作用域的bean标签中加<aop:scoped-proxy/>标签。如:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">

    <aop:scoped-proxy/>

</bean>

<bean id="userManager" class="com.foo.UserManager">

    <property name="userPreferences" ref="userPreferences"/>

</bean>

 

十一、      自定义作用域

第一步创建实现org.springframework.beans.factory.config.Scope接口的类。有4个方法:

Object get(String name, ObjectFactory objectFactory)从作用域中获取对象

Object remove(String name)作用域中移除对象

void registerDestructionCallback(String name, Runnable destructionCallback)注册作用域析构的回调方法

String getConversationId()处理作用域的会话标识

第二步装配作用域,用ConfigurableBeanFactoryregisterScope方法注册,方法的第一个参数是一个作用域的唯一名称(如'singleton''prototype'),第二个参数是作用域对象的实例。

第三步,使用:

<bean id="..." class="..." scope="thread"/>

 

十二、      初始化回调

实现org.springframework.beans.factory.InitializingBean接口允许容器在设置好bean的所有必要属性后,执行初始化事宜。InitializingBean接口仅指定了一个方法:

void afterPropertiesSet() throws Exception;

通常,要避免使用InitializingBean接口并且不鼓励使用该接口,因为这样会将代码和Spring耦合起来,有一个可选的方案是,可以在Bean定义中指定一个普通的初始化方法,然后在XML配置文件中通过指定init-method属性来完成。

 

十三、      析构回调

实现org.springframework.beans.factory.DisposableBean接口的bean允许在容器销毁该bean的时候获得一次回调。DisposableBean接口也只规定了一个方法:

void destroy() throws Exception;

通常,要避免使用DisposableBean标志接口而且不鼓励使用该接口,因为这样会将代码与Spring耦合在一起,有一个可选的方案是,在bean定义中指定一个普通的析构方法,然后在XML配置文件中通过指定destroy-method属性来完成。

 

十四、      缺省生命周期回调

如果使用统一的初始化和析构方法名称,可以使用beans标签上的default-init-methoddefault-destroy-method属性来指定所有该beans标签下所有bean的缺省初始化跟回调。

 

十五、      组合生命周期机制

初始化方法中的顺序:

@PostConstruct元注释

InitializingBeanafterPropertiesSet()定义

自定义init()方法配置

析构方法调用顺序:

@PreDestroy元注释

DisposableBeandestroy()定义

自定义destroy()方法

 

十六、      感知容器

实现BeanFactoryAware接口可以让bean与管理他的容器通信,该接口只有一个方法

void setBeanFactory(BeanFactory beanFactory) throws BeansException

org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean实现相同的功能,ObjectFactoryCreatingFactoryBean优于BeanFactoryAware的地方是它不违反IoC原则。

BeanNameAware接口则可以让bean获取自己在容器中的名称。

 

十七、      bean后置处理器

BeanPostProcessor接口有两个回调方法可供使用。当一个该接口的实现类被注册到容器后(注意:BeanPostProcessor的作用域是容器级的,它只和所在容器有关,不会对定义在另一个容器中的bean进行后置处理,即使这两个容器都处在同一层次上),对于由此容器所创建的每个bean实例在初始化方法(如afterPropertiesSet和任意已声明的init方法)调用前后,都会调用该接口的回调。

 

十八、      bean工厂处理器

BeanFactoryPostProcessor接口可以对bean的定义(配置元数据)进行处理。也就是说,Spring IoC容器允许BeanFactoryPostProcessor在容器实际实例化任何其它的bean之前读取配置元数据,并有可能修改它。同样地,BeanFactoryPostProcessor的作用域范围是容器级的。(容器启动时调用一次)

 

十九、      工厂bean

FactoryBean接口允许你将自己的工厂注册到IoC容器。对于该工厂bean的访问将返回该工厂bean返回的产品,如果要在程序中访问工厂bean本身,需要在获取对象的时候在对象名称前加"&"

 

二十、      补充:beans标签

名称

描述

default-autowire

no

byName

byType

constructor

autodetect

指定缺省的自动装配属性

 

default-dependency-check

default

none

simple

objects

all

设置缺省的依赖检查方式

 

default-destroy-method

字符串

设置缺省的析构方法名称

default-init-method

字符串

设置缺省的初始化方法名称

default-lazy-init

布尔值

设置缺省的延迟加载策略

default-merge

布尔值

设置缺省的集合合并策略

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值