Spring详解Word格式.docx
《Spring详解Word格式.docx》由会员分享,可在线阅读,更多相关《Spring详解Word格式.docx(63页珍藏版)》请在冰豆网上搜索。
>
构造注入:
IoC容器使用构造器来注入被依赖的实例。
constructor-argref="
配置构造注入的时候<
constructor-arg>
可以配置index属性,用于指定该构造参数值作为第几个构造参数值。
下表从0开始。
4,Spring容器和被管理的bean:
Spring有两个核心接口:
BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。
他们都可以代表Spring容器。
Spring容器是生成Bean实例的工厂,并管理Spring中的bean,bean是Spring中的基本单位,在基于Spring的javaEE工程,所有的组件都被当成bean处理。
包括数据源、Hibernate的SessionFactory、事务管理器。
①Spring容器:
Spring最基本的接口就是BeanFactory,
BeanFactory有很多实现类,通常使用XmlBeanFactory,但是对于大部分的javaEE应用而言,推荐使用ApplictionContext,它是BeanFactory的子接口,
ApplictionContext的实现类为FileSystemXmlApplicationContext和ClassPathXmlApplicationContext
FileSystemXmlApplicationContext:
基于文件系统的XML配置文件创建ApplicationContext;
ClassPathXmlApplicationContext:
基于类加载路径下的xml配置文件创建ApplicationContext。
②ApplicationContext的事件机制,
ApplicationContext事件机制是基于观察者设计模式实现的。
通过ApplicationEvent类和ApplicationListener接口,
其中ApplicationEvent:
容器事件,必须由ApplicationContext发布;
ApplicationListener:
监听器,可有容器内的任何监听器Bean担任。
③容器中bean的作用域:
singleton:
单例模式,在整个SpringIoC容器中,使用singleton定义的bean将只有一个实例;
prototype:
原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新实例;
request:
对于每次HTTP请求中,使用request定义的bean都将产生一个新实例,只有在web应用程序使用Spring时,该作用域才有效;
session:
同理
globalsession:
注意:
request和session作用域只在web应用中才生效,并且必须在web应用中增加额外的配置才会生效,为了让request,session两个作用域生效,必须将HTTP请求对象绑定到为该请求提供服务的线程上,这使得具有request和session作用域的Bean实例能够在后面的调用链中被访问。
当支持Servlet2.4及以上规范的web容器时,我们可以在web应用的web.xml增加如下Listener配置,该Listener负责为request作用域生效:
listener>
listener-class>
org.springframework.web.context.request.RequestContextListener<
/listener-class>
/listener>
如果仅使用了支持Servlet2.4以前规范的web容器,则该容器不支持Listener规范,故无法使用这种配置,可以使用Filter配置方式,我们可以在web应用的web.xml增加如下Filter配置:
filter>
filter-name>
requestContextFilter<
/filter-name>
filter-class>
org.springframework.web.filter.RequestContextFilter<
/filter-class>
/filter>
filter-mapping>
url-pattern>
/*<
/url-pattern>
/filter-mapping>
再如下面的代码:
beanid="
p"
class="
lee.Person"
scope="
request"
/>
这样容器就会为每次HTTP请求生成一个lee.Person的实例当该请求响应结束时,该实例也随之消失。
如果Web应用直接使用SpringMVC作为MVC框架,即使用SpringDispatchServlet或DispatchPortlet来拦截所有用户请求,则无需这些额外的配置,因为SpringDispatchServlet或DispatchPortlet已经处理了所有和请求有关的状态处理。
④获取容器的引用:
通常情况下:
Bean无需访问Spring容器,而是通过Spring容器访问的,即使需要手动访问Spring容器,程序也已通过类似下面的代码获取Spring容器的引用。
ApllicationContextcts=ClassPathApplalicationContext("
但在一些极端的情况下,可能Bean需要访问Spring容器。
Spring提供另一种方法访问Spring容器:
实现BeanFactoryAware接口的Bean,拥有访问Spring容器的能力,实现BeanFactoryAware的Bean被容器实例化后,会拥有一个引用指向创建他的BeanFactory。
BeanFactoryAware只有一个方法setBeanFactory(BeanFactorybeanFactory)该参数指向创建他的BeanFactory。
缺点:
污染了代码,使代码与Spring接口耦合在一起,因此没有特别的必要,建议不要直接访问容器。
5,Bean实例的创建方式及对应配置:
创建Bean的方法:
①调用构造器创建Bean实例;
②调用静态工厂方法创建Bean;
③调用实例工厂创建Bean。
调用静态工厂方法创建Bean:
class属性是必须的,但此时的class并不是指定Bean实例的实现类而是静态工厂类。
采用静态工厂类需要配置如下两个属性:
class静态工厂类的名字;
factory-method工厂方法(必须是静态的)。
如果静态工厂的方法有参数通过<
constructor-arg/>
元素知道。
调用实例工厂方法创建Bean:
使用实例工厂Bean时class属性无需指定,因Spring容器不会直接实例化该Bean,
创建Bean时需要如下属性:
factory-bean:
该属性为工厂Bean的ID;
factory-method:
该属性是定实例工厂的工厂方法。
6,入理解Spring容器中的Bean:
抽象Bean:
所有的抽象Bean,就是是定abstract属性为true的Bean,抽象Bean不能被实例化,抽象Bean的价值在于被继承
使用子Bean:
随着应用规模的增大,Spring配置文件的增长速度更快。
当应用中的组件越来越多,,Spring中的Bean配置也随之大幅度增加。
就会出现一中现象:
有一批配置Bean的信息完全相同,只有少量的配置不同。
怎么解决呢?
这时候就可以用Bean的继承来解决。
子Bean无法从父Bean继承如下属性:
depends-on,aotuwirwe,dependency-check,singleton,scope,lazy-iniyt这些属性总是子Bean定义,或采用默认值。
通过
为一个<
bean.../>
元素指定parent属性,即可指定该Bean是一个子Bean。
Bean继承与java中继承的区别:
Spring中的子bean和父Bean可以是不同类型,但java中的继承则可保证子类是一种特殊的父类;
Spring中的Bean的继承是实例之间的关系,因此只要表现在参数值的延续,而java中的继承是类之间的关系,主要表现为方法、属性之间的延续;
Spring中的子Bean不可以作为父Bean使用,不具备多态性,java中的子类完全可以当成父类使用。
Bean的生命周期:
①singleton与prototype的区别:
Spring可以精确的知道该Bean何时被创建、初始化、销毁。
对于singleton作用域的Bean,每次客户端请求Spring容器总会返回一个共享的实例。
Spring容器仅仅负责创建Bean,当容器创建了Bean的实例后,Bean实例完全交给客户端代码管理,容器不在跟踪其生命周期。
每次客户端请求prototype作用域的Bean,都会为他创建一个新的实例,
②依赖关系注入后的行为:
Spring提供两种方法在Bean全部属性设置成功后执行特定的行为:
使用init-method属性;
该Bean实现InitializingBean接口
第一种方法:
使用init-method属性指定某个方法在Bean全部属性依赖关系设置结束后自动执行。
使用这种方法不需要将代码与Spring的接口耦合在一起,代码污染少;
第二种方法:
实现Initializing接口,该接口有一个方法voidafterPropertiesSet()throwsException,虽然实现次接口一样可以在Bean全部属性设置成功后执行特定的行为,但是污染了代码,是侵入式设计,因此不推荐使用。
如果即采用init-method属性指定初始化方法,又实现InitializingBean接口来指定初始化方法,先执行initializingBean接口中定义的方法,再执行init-method属性指定的方法。
③Bean销毁之前行为:
与定制初始化相似,Spring也提供两种方式定制Bean实例销毁之前的特定行为,如下:
使用destroy-method属性:
实现DisposableBean接口:
如果即采用destroy-method属性指定销毁之前的方法,又实现DisposableBean接口来指定指定销毁之前的方法,与②类似。
④default-init-method与default-destroy-method属性,指定了所有的Bean都会执行此方法,而不是单个的Bean。
协调作用域不同步的Bean:
描述:
当Spring容器中作用域不同的Bean相互依赖时,可能出现一些问题:
当两个singleton作用域Bean存在依赖关系时,或当prototype作用依赖singleton作用域的Bean时,通过属性定义依赖关系即可。
、
但是,当singleton作用域的Bean依赖prototype作用域Bean时,singleton作用域的Bean只有一次初始化的机会,他的依赖关系也只有在初始化阶段被设置,而他所依赖的prototype作用域的Bean则会不断的产生新的Bean实例。
解决方案:
第一种:
部分放弃依赖注入:
singleton作用域的Bean每次需要prototype作用域的Bean,则主动向容器请求新的Bean实例。
第二种:
利用方法注入。
第一种方案肯定是不好的,代码主动请求新的Bean实例,必然会导致与SpringAPI耦合,造成代码严重污染。
通常情况下采用第二中方式。
方法注入通常使用lookup方法注入,利用lookup方法注入可以让Spring容器重写容器中Bean的抽象方法或具体方法,返回查找容器中的其他Bean,被查找的Bean通常是non-singletonBean(尽管也可以是singleton).
如:
publicclassSteelAxeimplementsAxe{
//每执行一次加一
privateintcount;
publicString
chop(){
return++count;
}
publicabstractclassChineseimplementsPerosom{
privateAxeaxe;
//定义一个抽象方法,该方法将由Spring负责实现
publicabstractAxecreateAxe();
publicvoidsetAxe(Axeaxe){
thisaxe=axe;
publicAxegetAxe(){
returnaxe;
在Spring配置文件中配置:
steelAxe"
...SteelAxe"
prototype"
/bean>
chinese"
..Chinese"
>
lookup-mehtodname="
createAxe"
bean="
axe"
容器中的工厂Bean:
此处的工厂Bean与前面介绍的实例工厂方法创建Bean、静态工厂创建Bean有所区别:
前面的那些工厂是标准的工厂模式,Spring只是负责调用工厂方法来创建Bean实例;
此处工厂Bean是Spring的一种特殊Bean,这种工厂Bean必须实现FactoryBean接口。
FactoryBean接口是工厂Bean标准的工厂Bean的接口,实现该接口的Bean只能当工厂Bean使用,当我们将工厂Bean部署在容器中,并通过getBean()方法来获取工厂Bean,容器不会返回FactoryBean实例而是FactoryBean的产品。
FactoryBean提供了三个方法:
ObjectgetObject();
ClassgetObjectType();
booleanisSingleton();
publicclassPersonFactoryimplementsFactoryBean{
Personp=null;
publicObjectgetObject()throwsException{
if(p==null){
p
=newChinense();
returnp;
publicClassgetObjectType(){
returnChinese.class;
publicbooleanisSingleton(){
returntrue;
!
--配置一个FactoryBean,和普通的Bean一样-->
publicstaticvoidmain(Stringargs[]){\
//以classpth下的bean.xml创建Reource对象
ClassPathResourcere=newClasspathResource("
//创建BeanFactory
XmlBeanFactoryfactory=newXmlBeanFactory(re);
Personp=(Person)factory.getBean("
//如需要获取FactoryBean本身则应该在beanid前加&
&
对于初学者可能无法体会到工厂bean的作用,实际上,FactoryBean是Spring中非常有用的接口。
例如:
TransationProxyFactroyBean,这个工厂转为目标Bean创建事务代理.
7,深入理解依赖关系配置
组件与组件之间的耦合,采用依赖注入管理,但是普通的javabean属性值,应直接在代码里设置。
对于singleton作用域的bean,如果没有强制取消其预初始化行为,系统会在创建Spring容器时预初始化所有的singleton作用域的bean,与此同时,该bean依赖的bean也一起被实例化。
BeanFactory与ApplicationContext实例化容器中的bean的时机不同,前者等到程序需要Bean实例才创建Bean
后者会预初始化容器中的所有Bean。
因为采用ApplicationContext作为Spring的容器,创建容器时,会创建容器中所有singleton作用域的所有bean,因此可能需要更多的系统资源,但是一旦创建成功。
应用后面的响应速度会很快,因此,对于普通的javaEE而言,建议使用ApplicationContext作为Spring的容器。
Bean实例4中属性值的设置:
value;
ref;
bean;
list、set、map、props
①设置普通属性值value,略;
②配置合作者Bean
ref
可以为ref元素指定两个属性:
bena、Local
bean:
引用在不同一份XML配置文件中的其他Bean实例的ID属性值;
Local:
引用同一份XML配置文件的其他Beanid属性值。
也可以不配置以上两个属性。
③组合属性名称:
publicclass
A{
privatePersonp=newPerson();
set/get....
Spring配置文件
a"
A"
p.name"
value="
aaa"
④注入嵌套Bean:
//属性为嵌套Bean不能由Spring容器直接访问,因此没有id属性
beanclass="
..."
/property>
⑤注入集合值:
list>
value>
/value>
/list>
map>
//每一个entry配置一个key-value对
entry>
key>
.<
/key>
/entry>
/map>
set>
bean>
reflocal="
/set>
props>
propkey="
.....<
/prop>
/props>
⑥注入方法返回值:
publicclassValueGenrator{
publicintgetValue(){
return6;
publicstaticintgetStaticValue(){
return9;
valueGenrator"
lee.ValueGenrator"
son1"
Son"
age"
org.springframework.bean.factory.congfig.MethodInvokignFactoryBean"
//配置非静态方法
targetObject"
//配置静态方法
--
targetClass"
-->
targetMehtod"
getStaticValue/>
8,