IOC 容器
org.springframework.beans 和 org.springframework.context包是spring IOC容器的基础。
BeanFactory 和 ApplicationContext:BeanFactory提供的高级配置机制,使得管理各种对象成为可能。而ApplicationContext是BeanFactory的扩展,功能进一步增强。简单而言,BeanFactory 提供了
配置框架以及基本功能,而ApplicationContext则增加了支持企业核心内容的功能,如事物处理和AOP、国际化等。ApplicationContext完全由BeanFactory扩展而来,因而具备BeanFactory的所有功能。
容器和bean
在spring中,那些组成应用程序的主体以及由Spring ICO容器所管理的对象,称为bean。bean的定义和bean之间的依赖关系则通过配置元数据来描述。
Spring IOC 容器的实际代表者和核心接口: BeanFactory, 它的职责包括:实例化、定位、配置应用程序中的对象以及建立这些对象间的依赖。
最常用的BeanFactory的实现:XmlBeanFactory.
Spring IOC 容器读取配置元数据,并通过它对应用中各个对象进行实例化、配置以及组装。
配置元数据的格式:基于xml和基于注解
Spring IOC 容器实例化:
Spring 配置文件分拆:
bean命名:
每个bean都有一个或多个id,这些id在当前IOC容器中必须唯一。如果一个bean有多个id,那么其他的id在本质上将被认为是别名。bean的name并不是必须的,如果没有指定,
那么容器将为其生成一个唯一的name。
别名:
<alias name="fromName" alias="toName"/>
如果在容器中存在名为fromName的bean定义,在增加别名定义后,也可以用toName来引用。
Bean实例化:
1、构造器实例化;
采用构造器实例化bean时,Spring对class并没有特殊要求,只需要bean的class有默认的空构造器。
采用静态工厂方法实例化时,除了指定class属性外,还需要通过factory-method属性来指定创建bean实例的工厂方法。Spring 将调用此方法返回实例化对象。
3、实例工厂方法实例化;
用来实例化的非静态实例工厂方法位于另外一个bean中,容器将调用该bean的工厂方法来创建一个新的bean实例。
依赖注入
依赖注入背后的原理是对象之间的依赖关系。
两种方式:构造器注入和setter注入
构造器注入:通过调用带参数的构造器实现
因为此实例中参数类型是非常明确的,所有在配置中没有指定构造参数顺序和类型也会工作,但是当参数类型相同或者使用简单的参数类型时,Spring将无法根据参数类型进行匹配。
此时可以使用构造器参数类型匹配或构造器参数索引。
构造器参数类型匹配:
构造器参数索引
注意,index是从0开始的。
setter方法注入:
Lookup方法注入:
此方法注入是用于依赖bean和协作bean的作用域不同的情况,比如一个singleton bean需要引用一个prototype bean。
此实例中,CommandManager是singleton,在process中需要使用一个prototype的Command bean。 我们将CommandManager声明为abstract,并创建一个abstract方法用于创建prototype的Command,但是不实现;
bean依赖关系处理:
一、根据定义bean的配置文件创建并初始化BeanFacotry实例;
二、当这些bean被实际创建时,他相关的依赖也将提供给该bean;
三、每个属性或构造器参数既可以是一个实际的值,也可以是对容器中另外一个bean的引用。
四。每个指定的属性或者构造器参数值必须能够被转换成特定格式或者构造器参数所需的类型
在默认情况下,ApplicationContext实现中的bean采用的是提前实例化的singleton模式,这样做将带来时间和内存的开销,但是好处是ApplicationContext被加载的时候可以尽早的发现一些配置问题。不过用户也可以根据
需要采用延迟实例化的方式。
循环依赖:当一个类A,需要通过构造器注入类B,而类B又需要通过构造器注入类A,这样spring ioc容器将检测出循环引用,并抛出BeanCurrentlyInCreationException异常。
静态工厂方法注入:
传给static工厂方法的参数由constructor-arg元素提供,这与使用构造器注入时完全一样
idref元素
将容器内其他bean的id传给<constructor-arg/>或<prperty/>元素,同时提供错误验证功能。
只是传了bean的id值,并不是bean的引用,这里等同于:
但是这里没有错误验证功能,也就是说采用idref的时候,会验证theTargetBean是否存在。
使用idref时,如果引用的bean在同一个xml配置文件中,也可以用
<idref local="" />
引用其他bean
ref元素
<ref bean="someBean" />
引用同一容器或者父容器中的任何bean,无论是否在同一个xml配置文件中。bean的值既可以是bean的id值,也可以是name的值。
<ref local="someBean" />
如果所引用的bean在同一个xml配置文件中,可以用这种方式,但是local的属性值必须是目标bean的id值。
<ref parent="someBean" />
如果引用的目标bean在父容器中,可以使用此方式,parent属性值既可以是目标bean的id值,也可以是name属性值,而起目标bean必须在当前容器的父容器中。
内部bean
指在一个bean的<property />或 <constructor-arg />元素中使用<bean/>元素定义的bean。内部bean定义不需要id和name属性,即使指定也会被容器忽略。。
内部bean总是匿名的且他们总是prototype模式的,同时将内部bean注入到包含该内部bean之外的bean是不可能的
集合的合并:
从2.0开始,Spring IOC容器将支持集合的合并
此实例中,child bean的adminEmails属性的<props/>元素使用了merge=true属性,当child bean被容器实际解析以及实例化时,其adminEmails将与父集合的adminEmails属性进行合并.
合并功能仅在spring 2.0以及后版本中可用,不同的集合类型是不能合并的,比如Map类型的不能和list合并。
<null />元素
此元素用于处理null值,Spring会把属性的空参数当做空字符串处理;
这等同于java代码: example.setEmail("");
这等同于java代码: example.setEmail(null);
depends-on:
多数情况下,一个bean对另一个bean的依赖最简单的做法就是将一个bean设置为另外一个bean的属性。在xml配置文件中最常用的就是使用 <ref />元素,但是
在少数情况下,有时候bean之间的依赖关系并不是那么直接。depends-on属性可以用于当前bean初始化之前显示的强制一个或者多个bean初始化。
如果要表达多个bean的依赖,可以再'depends-on'中指定多个bean名字,用逗号、空格、分号等隔开。
它同时也可以用来指定相应的销毁时的依赖(针对singleton bean),指定的bean会在当前bean销毁之前被销毁。
延迟初始化bean
如果你不想让一个singleton bean在ApplicationContext初始化时提前实例化,那么可以将bean设置为延迟实例化
如果一个bean设置为延迟实例化,而另一个非延迟实例化的singleton bean依赖它,那当IOC容器实例化singleton bean时,会确保它依赖的延迟bean也实例化
在容器层次上控制延迟初始化:
autowire 自动装配协作者:
Spring IOC 可以自动装配相互协作bean之间的关联关系
byName 根据属性的名字自动装配,此选项检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配;
byType 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,将抛出异常;如果没有找到匹配的bean,
则什么事都不发生,如果希望抛出异常,可以设置dependency-check="objects";
constructor 与byType类似,但是它应用于构造器参数,如果没有找到匹配的bean,那么会抛出异常;
autodetect 通过bean的自省机制来决定使用construtor还是byType,如果发现默认的构造器,则使用byType;
如果使用setter和构造器注入依赖的话,那么将总是覆盖自动装配,而起目前也不支持简单类型的自动装配,简单类型包括基本类型、String,Class以及简单类型的数组。
优点:
减少配置的数量;
使配置与Java代码同步更新,比如,如果你需要给一个java类增加一个依赖,那么该依赖将会被自动实现而不需要修改配置;
缺点:
如果装配不明确,将出现难以预料的结果;
如果需要根据配置文件生成文档的话,自动装配将会没法生成依赖信息,所以spring所管理的对象之间的关联关系不能清晰文档化;
bean定义中设置 primary 属性为 true,将该bean设置为首选自动装配bean;
bean定义中设置autowire-candidate属性设置为false,此bean将排除在自动装配之外,容器在查找自动装配对象时将不考虑此bean;
<beans />元素的 default-autowire-candidates属性用来 对bean名字进行模式匹配,如自动匹配限制在名字以Respository结尾的bean,则可以设置其值为*Repository,
但是如果某个bean满足名字匹配模式,而它的autowire-candidate属性设置成了false,则不会被装配。
bean作用域
Singleton作用域:
当一个bean的作用域为singleton,那么Spring IOC容器中只存在一个共享的bean实例。
和GOF模式中的Singleton模式完全不同,GOF模式中的singleton对象范围是指在一个ClassLoader中指定class创建的实例有且仅有一个。
Singleton作用域是Spring中的缺省作用域;
Prototype作用域:
prototype作用域的bean会导致在每次对该bean请求时,都会创建一个新的bean实例;
一般来说,对有状态的bean应该使用prototype作用域,而无状态的bean则应该使用singleton作用域;
配置实例: <bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
Spring 不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装配完一个prototype实例后,将它交给客户端,虽然就对该bean不闻不问了。
不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,但是prototype例外。
如果一个singleton类型的bean A需要引用另一个prototype类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的bean B 实例,这个时候需要采用方法注入;
Request作用域:
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction 实例,且该实例仅在当前HTTP request内有效。
Session作用域:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
针对某个HTTP Session, Spring容器会根据userPreferences bean定义创建一个全新的实例,且该实例仅在当前HTTP Session内有效。
Global Session作用域:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
该作用越类似于HTTP Session作用域,但是它仅仅在基于portlet的web应用中才有意义。
作用域bean与依赖:
request、session、globalSession和自定义作用域需要<aop:scoped-proxy/>元素;
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
此实例中,singleton bean userManager中注入了一个session作用域的userPreferences bean,这意味着userManager在理论上只会操作同一个userPreferences对象。
所以此时需要使用AOP代理
<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>
此时注入的对象其实是实现了和UserPreferences类一样的公共接口,即就是代理对象,并且不论底层选择了何种作用域,容器都能获取到真正的UserPreferences对象
但是<aop:scoped-proxy />不能和singleton或prototype的bean一起使用,所以,如果将一个prototype类型的bean注入到singleton中时需要使用lookup方法注入法
默认情况下,当一个bean有<aop:scope-proxy />标记时,Spring容器将为它创建一个基于CGLIB的类代理,此时需要将CGLIB库加到classpath中。CGLIB代理仅仅拦截public方法的调用;
如果想选择JDK代理,则需要将<aop:scoped-proxy />的属性proxy-target-class设置为false,但是此时类必须要实现至少一个接口。
自定义作用域:
自动以作用域需要实现 org.springframework.beans.factory.config.Scope接口
此接口提供四个方法来处理获取对象,移除对象和必要的时候销毁对象:
一、Object get(String name, ObjectFactory objectFactory) 从作用域中获取对象;
二、remove(String name) 从作用域中移除对象;
三、registerDestructionCallback(String name, Runnable destructionCallback) 注册作用域析构的回调方法,当作用域销毁或作用域中的某个对象销毁时会执行;
四、getConversationId() 处理作用域的会话标识。
org.springframework.beans 和 org.springframework.context包是spring IOC容器的基础。
BeanFactory 和 ApplicationContext:BeanFactory提供的高级配置机制,使得管理各种对象成为可能。而ApplicationContext是BeanFactory的扩展,功能进一步增强。简单而言,BeanFactory 提供了
配置框架以及基本功能,而ApplicationContext则增加了支持企业核心内容的功能,如事物处理和AOP、国际化等。ApplicationContext完全由BeanFactory扩展而来,因而具备BeanFactory的所有功能。
容器和bean
在spring中,那些组成应用程序的主体以及由Spring ICO容器所管理的对象,称为bean。bean的定义和bean之间的依赖关系则通过配置元数据来描述。
Spring IOC 容器的实际代表者和核心接口: BeanFactory, 它的职责包括:实例化、定位、配置应用程序中的对象以及建立这些对象间的依赖。
最常用的BeanFactory的实现:XmlBeanFactory.
Spring IOC 容器读取配置元数据,并通过它对应用中各个对象进行实例化、配置以及组装。
配置元数据的格式:基于xml和基于注解
Spring IOC 容器实例化:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"services.xml","daos.xml"}); BeanFactory factory = context;
Spring 配置文件分拆:
<beans> <import resource="services.xml"/> <import resource="resources/messageSource.xml"/> <import resource="/resources/themeSource.xml"/> <bean id="bean1" class="..."/> <bean id="bean2" class="..."/> </beans>所有的import元素必须在<bean/>元素之前完成bean定义的导入。
bean命名:
每个bean都有一个或多个id,这些id在当前IOC容器中必须唯一。如果一个bean有多个id,那么其他的id在本质上将被认为是别名。bean的name并不是必须的,如果没有指定,
那么容器将为其生成一个唯一的name。
别名:
<alias name="fromName" alias="toName"/>
如果在容器中存在名为fromName的bean定义,在增加别名定义后,也可以用toName来引用。
Bean实例化:
1、构造器实例化;
采用构造器实例化bean时,Spring对class并没有特殊要求,只需要bean的class有默认的空构造器。
<bean id="exampleBean" class="examples.ExampleBean"/>2、静态工厂方法实例化;
采用静态工厂方法实例化时,除了指定class属性外,还需要通过factory-method属性来指定创建bean实例的工厂方法。Spring 将调用此方法返回实例化对象。
<bean id="exampleBean" class="examples.ExampleBean2" factory-method="createInstance"/>createInstance()必须是一个static方法。
3、实例工厂方法实例化;
用来实例化的非静态实例工厂方法位于另外一个bean中,容器将调用该bean的工厂方法来创建一个新的bean实例。
<bean id="serviceLocator" class="com.foo.DefaultServiceLocator"></bean> <bean id="exampleBean" factory-bean="serviceLocator" factory-method="createInstance"/>class属性必须为空,factory-bean指定为当前容器中包含的工厂方法的bean的名称,factory-method指向工厂bean中的工厂方法。
依赖注入
依赖注入背后的原理是对象之间的依赖关系。
两种方式:构造器注入和setter注入
构造器注入:通过调用带参数的构造器实现
package x.y; public class Foo { public Foo(Bar bar, Baz baz) { // ... } } <beans> <bean name="foo" class="x.y.Foo"> <constructor-arg> <bean class="x.y.Bar"/> </constructor-arg> <constructor-arg> <bean class="x.y.Baz"/> </constructor-arg> </bean> </beans>
因为此实例中参数类型是非常明确的,所有在配置中没有指定构造参数顺序和类型也会工作,但是当参数类型相同或者使用简单的参数类型时,Spring将无法根据参数类型进行匹配。
此时可以使用构造器参数类型匹配或构造器参数索引。
构造器参数类型匹配:
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
构造器参数索引
<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg index="0" value="7500000"/> <constructor-arg index="1" value="42"/> </bean>
注意,index是从0开始的。
setter方法注入:
<beans> <bean name="foo" class="x.y.Foo"> <property name="age" value="24" /> <property name="anotherBean" ref="anotherBeanName" /> </bean> </beans>
Lookup方法注入:
此方法注入是用于依赖bean和协作bean的作用域不同的情况,比如一个singleton bean需要引用一个prototype bean。
public abstract class CommandManager { public Object process(Object commandState) { // grab a new instance of the appropriate Command interface Command command = createCommand(); // set the state on the (hopefully brand new) Command instance command.setState(commandState); return command.execute(); } // okay... but where is the implementation of this method? protected abstract Command createCommand(); }
此实例中,CommandManager是singleton,在process中需要使用一个prototype的Command bean。 我们将CommandManager声明为abstract,并创建一个abstract方法用于创建prototype的Command,但是不实现;
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype"> <!-- inject dependencies here as required --> </bean> <!-- commandProcessor uses statefulCommandHelper --> <bean id="commandManager" class="fiona.apple.CommandManager"> <lookup-method name="createCommand" bean="command"/> </bean>
bean依赖关系处理:
一、根据定义bean的配置文件创建并初始化BeanFacotry实例;
二、当这些bean被实际创建时,他相关的依赖也将提供给该bean;
三、每个属性或构造器参数既可以是一个实际的值,也可以是对容器中另外一个bean的引用。
四。每个指定的属性或者构造器参数值必须能够被转换成特定格式或者构造器参数所需的类型
在默认情况下,ApplicationContext实现中的bean采用的是提前实例化的singleton模式,这样做将带来时间和内存的开销,但是好处是ApplicationContext被加载的时候可以尽早的发现一些配置问题。不过用户也可以根据
需要采用延迟实例化的方式。
循环依赖:当一个类A,需要通过构造器注入类B,而类B又需要通过构造器注入类A,这样spring ioc容器将检测出循环引用,并抛出BeanCurrentlyInCreationException异常。
静态工厂方法注入:
<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance"> <constructor-arg ref="anotherExampleBean"/> <constructor-arg ref="yetAnotherBean"/> <constructor-arg value="1"/> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
传给static工厂方法的参数由constructor-arg元素提供,这与使用构造器注入时完全一样
idref元素
将容器内其他bean的id传给<constructor-arg/>或<prperty/>元素,同时提供错误验证功能。
<bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <idref bean="theTargetBean" /> </property> </bean>
只是传了bean的id值,并不是bean的引用,这里等同于:
<bean id="theTargetBean" class="..."/> <bean id="theClientBean" class="..."> <property name="targetName"> <value>theTargetBean</value> </property> </bean>
但是这里没有错误验证功能,也就是说采用idref的时候,会验证theTargetBean是否存在。
使用idref时,如果引用的bean在同一个xml配置文件中,也可以用
<idref local="" />
引用其他bean
ref元素
<ref bean="someBean" />
引用同一容器或者父容器中的任何bean,无论是否在同一个xml配置文件中。bean的值既可以是bean的id值,也可以是name的值。
<ref local="someBean" />
如果所引用的bean在同一个xml配置文件中,可以用这种方式,但是local的属性值必须是目标bean的id值。
<ref parent="someBean" />
如果引用的目标bean在父容器中,可以使用此方式,parent属性值既可以是目标bean的id值,也可以是name属性值,而起目标bean必须在当前容器的父容器中。
内部bean
指在一个bean的<property />或 <constructor-arg />元素中使用<bean/>元素定义的bean。内部bean定义不需要id和name属性,即使指定也会被容器忽略。。
<bean id="outer" class="..."> <property name="target"> <bean class="com.example.Person"> <!-- this is the inner bean --> <property name="name" value="Fiona Apple"/> <property name="age" value="25"/> </bean> </property> </bean>
内部bean总是匿名的且他们总是prototype模式的,同时将内部bean注入到包含该内部bean之外的bean是不可能的
集合的合并:
从2.0开始,Spring IOC容器将支持集合的合并
<beans> <bean id="parent" abstract="true" class="example.ComplexObject"> <property name="adminEmails"> <props> <prop key="administrator">administrator@example.com</prop> <prop key="support">support@example.com</prop> </props> </property> </bean> <bean id="child" parent="parent"> <property name="adminEmails"> <!-- the merge is specified on the *child* collection definition --> <props merge="true"> <prop key="sales">sales@example.com</prop> <prop key="support">support@example.co.uk</prop> </props> </property> </bean> <beans>
此实例中,child bean的adminEmails属性的<props/>元素使用了merge=true属性,当child bean被容器实际解析以及实例化时,其adminEmails将与父集合的adminEmails属性进行合并.
合并功能仅在spring 2.0以及后版本中可用,不同的集合类型是不能合并的,比如Map类型的不能和list合并。
<null />元素
此元素用于处理null值,Spring会把属性的空参数当做空字符串处理;
<bean class="ExampleBean"> <property name="email"> <value/> </property> </bean>
这等同于java代码: example.setEmail("");
<bean class="ExampleBean"> <property name="email"> <null /> </property> </bean>
这等同于java代码: example.setEmail(null);
depends-on:
多数情况下,一个bean对另一个bean的依赖最简单的做法就是将一个bean设置为另外一个bean的属性。在xml配置文件中最常用的就是使用 <ref />元素,但是
在少数情况下,有时候bean之间的依赖关系并不是那么直接。depends-on属性可以用于当前bean初始化之前显示的强制一个或者多个bean初始化。
<bean id="beanOne" class="ExampleBean" depends-on="manager"/> <bean id="manager" class="ManagerBean" />
如果要表达多个bean的依赖,可以再'depends-on'中指定多个bean名字,用逗号、空格、分号等隔开。
它同时也可以用来指定相应的销毁时的依赖(针对singleton bean),指定的bean会在当前bean销毁之前被销毁。
延迟初始化bean
如果你不想让一个singleton bean在ApplicationContext初始化时提前实例化,那么可以将bean设置为延迟实例化
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
如果一个bean设置为延迟实例化,而另一个非延迟实例化的singleton bean依赖它,那当IOC容器实例化singleton bean时,会确保它依赖的延迟bean也实例化
在容器层次上控制延迟初始化:
<beans default-lazy-init="true"> <!-- no beans will be pre-instantiated... --> </beans>
autowire 自动装配协作者:
Spring IOC 可以自动装配相互协作bean之间的关联关系
byName 根据属性的名字自动装配,此选项检查容器并根据名字查找与属性完全一致的bean,并将其与属性自动装配;
byType 如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配。如果存在多个该类型的bean,将抛出异常;如果没有找到匹配的bean,
则什么事都不发生,如果希望抛出异常,可以设置dependency-check="objects";
constructor 与byType类似,但是它应用于构造器参数,如果没有找到匹配的bean,那么会抛出异常;
autodetect 通过bean的自省机制来决定使用construtor还是byType,如果发现默认的构造器,则使用byType;
如果使用setter和构造器注入依赖的话,那么将总是覆盖自动装配,而起目前也不支持简单类型的自动装配,简单类型包括基本类型、String,Class以及简单类型的数组。
优点:
减少配置的数量;
使配置与Java代码同步更新,比如,如果你需要给一个java类增加一个依赖,那么该依赖将会被自动实现而不需要修改配置;
缺点:
如果装配不明确,将出现难以预料的结果;
如果需要根据配置文件生成文档的话,自动装配将会没法生成依赖信息,所以spring所管理的对象之间的关联关系不能清晰文档化;
bean定义中设置 primary 属性为 true,将该bean设置为首选自动装配bean;
bean定义中设置autowire-candidate属性设置为false,此bean将排除在自动装配之外,容器在查找自动装配对象时将不考虑此bean;
<beans />元素的 default-autowire-candidates属性用来 对bean名字进行模式匹配,如自动匹配限制在名字以Respository结尾的bean,则可以设置其值为*Repository,
但是如果某个bean满足名字匹配模式,而它的autowire-candidate属性设置成了false,则不会被装配。
bean作用域
Singleton作用域:
当一个bean的作用域为singleton,那么Spring IOC容器中只存在一个共享的bean实例。
和GOF模式中的Singleton模式完全不同,GOF模式中的singleton对象范围是指在一个ClassLoader中指定class创建的实例有且仅有一个。
Singleton作用域是Spring中的缺省作用域;
Prototype作用域:
prototype作用域的bean会导致在每次对该bean请求时,都会创建一个新的bean实例;
一般来说,对有状态的bean应该使用prototype作用域,而无状态的bean则应该使用singleton作用域;
配置实例: <bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
Spring 不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装配完一个prototype实例后,将它交给客户端,虽然就对该bean不闻不问了。
不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,但是prototype例外。
如果一个singleton类型的bean A需要引用另一个prototype类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的bean B 实例,这个时候需要采用方法注入;
Request作用域:
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
针对每次HTTP请求,Spring容器会根据loginAction bean定义创建一个全新的LoginAction 实例,且该实例仅在当前HTTP request内有效。
Session作用域:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
针对某个HTTP Session, Spring容器会根据userPreferences bean定义创建一个全新的实例,且该实例仅在当前HTTP Session内有效。
Global Session作用域:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
该作用越类似于HTTP Session作用域,但是它仅仅在基于portlet的web应用中才有意义。
作用域bean与依赖:
request、session、globalSession和自定义作用域需要<aop:scoped-proxy/>元素;
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
此实例中,singleton bean userManager中注入了一个session作用域的userPreferences bean,这意味着userManager在理论上只会操作同一个userPreferences对象。
所以此时需要使用AOP代理
<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>
此时注入的对象其实是实现了和UserPreferences类一样的公共接口,即就是代理对象,并且不论底层选择了何种作用域,容器都能获取到真正的UserPreferences对象
但是<aop:scoped-proxy />不能和singleton或prototype的bean一起使用,所以,如果将一个prototype类型的bean注入到singleton中时需要使用lookup方法注入法
默认情况下,当一个bean有<aop:scope-proxy />标记时,Spring容器将为它创建一个基于CGLIB的类代理,此时需要将CGLIB库加到classpath中。CGLIB代理仅仅拦截public方法的调用;
如果想选择JDK代理,则需要将<aop:scoped-proxy />的属性proxy-target-class设置为false,但是此时类必须要实现至少一个接口。
自定义作用域:
自动以作用域需要实现 org.springframework.beans.factory.config.Scope接口
此接口提供四个方法来处理获取对象,移除对象和必要的时候销毁对象:
一、Object get(String name, ObjectFactory objectFactory) 从作用域中获取对象;
二、remove(String name) 从作用域中移除对象;
三、registerDestructionCallback(String name, Runnable destructionCallback) 注册作用域析构的回调方法,当作用域销毁或作用域中的某个对象销毁时会执行;
四、getConversationId() 处理作用域的会话标识。
相关推荐
个人学习spring框架时记录的笔记,纯手敲,SpringIOC+SpringMVC学习笔记,有兴趣的可以参考
这份"Spring框架学习笔记"涵盖了Spring框架的基础知识、核心组件以及高级特性,对于初学者来说是一份宝贵的资料。 一、Spring框架概述 Spring框架是为了解决企业应用开发的复杂性而设计的,它提供了一个全面的基础...
依赖注入:Dependency Injection IOC的作用:降低程序间的偶合(依赖关系) 依赖关系的管理:以后都交给spring来维护 ... ref:用于指定其他bean类型数据,它所指的是在spring的IOC容器中出现的bean
Spring框架是Java开发中不可或缺的一部分,它为开发者提供了强大的依赖注入(IOC)和面向切面编程(AOP)功能,以及用于构建Web应用程序的MVC框架。Spring Boot则是基于Spring框架构建的应用程序启动器,旨在简化...
本资料“Spring学习笔记&源码”是基于网易云课堂黑马程序员的Spring四天精通课程,旨在帮助学习者深入理解和实践Spring框架。 笔记部分可能会涵盖以下内容: 1. **Spring概述**:介绍Spring框架的历史、特点和主要...
在本次的Java Spring框架学习笔记中,将对Spring框架的核心概念进行详细解析,包括Spring的 IOC(控制反转)、AOP(面向切面编程)、jdbcTemplate、事务管理、Spring5新特性以及与Mybatis的整合。本学习笔记提供了...
马士兵老师是知名的Java教育专家,他的Spring框架学习笔记深入浅出,对于初学者和进阶者来说都是一份宝贵的资源。这份笔记涵盖了Spring的核心概念、配置、AOP(面向切面编程)、DI(依赖注入)等关键知识点。 1. **...
标题和描述均提到了“spring指南学习笔记”,这意味着文档聚焦于Spring框架的学习心得与关键概念。Spring是一个开源的Java企业级应用框架,以其强大的依赖注入(Dependency Injection, DI)和面向切面编程(Aspect ...
**Spring-IoC 复习笔记** Spring 框架是 Java 开发中不可或缺的一部分,其核心特性之一就是依赖注入(Dependency Injection,简称 DI),也称为控制反转(Inversion of Control,简称 IoC)。IoC 是一种设计模式,...
### Spring学习笔记(精华全记录) #### Spring框架概述 Spring框架源自Rod Johnson的个人项目,最初于2002年末发布。Spring并非一开始就作为一个完整的框架出现,而是从一个项目逐步发展而来。随着项目的成熟,...
### Spring.NET学习笔记-实现一个简易的IoC框架 #### 一、背景介绍与理论基础 在.NET领域中,Spring.NET框架是一个非常重要的轻量级框架,它支持依赖注入(Dependency Injection, DI)和面向切面编程(Aspect ...
本笔记将深入探讨Spring框架的核心概念和主要功能,帮助你全面理解并掌握这一强大的工具。 一、Spring概述 Spring是一个开源的Java平台,它提供了一个全面的编程和配置模型,用于现代Java应用。其核心是IoC容器,...
以下是对Spring框架中IoC、DI和AOP等关键知识点的详细解析。 ### 1. **IoC(Inversion of Control,控制反转)** IoC是Spring的核心概念之一,它将对象的创建和管理权交给了容器,而不是由对象自身负责。这样可以...
这份"Spring学习笔记+学习源码.zip"资源包含了深入学习Spring及其相关技术的知识点,以及实践代码,对提升Spring技能将大有裨益。 首先,我们来详细讨论Spring框架的主要组件和功能: 1. **依赖注入(Dependency ...
以下将详细介绍Spring学习笔记中的主要知识点。 **面向抽象编程** 面向抽象编程是一种设计原则,强调在代码中使用接口或抽象类,而不是具体实现类。这使得系统更具有灵活性,易于扩展和维护。在Spring框架中,我们...
总之,《Spring技术内幕 学习笔记》涵盖了Spring框架的众多核心知识点,从IoC容器、AOP到Web开发和数据访问,对于提升Spring开发技能具有很高的价值。通过深入学习和实践,开发者能够更好地理解和掌握Spring框架,...
总的来说,这篇Spring 2.5学习笔记涵盖了Spring的基础知识,如面向抽象编程、Jdom使用、Spring环境搭建以及核心特性IOC和DI的实现。同时,它也涉及到了SSH整合的相关内容,为开发者提供了全面学习Spring以及如何与...
在"Spring笔记.pdf"、"Spring笔记1.pdf"和"Spring编程学习笔记2.pdf"中,你将找到关于这些概念的详细解释和实例,包括XML配置、注解驱动的编程、AOP的实现方式、Spring Boot的快速启动指南以及Spring MVC的...
Spring框架的核心特性包括轻量级、控制反转(IoC)、面向切面编程(AOP)、容器化管理和框架集合,使其在与其他框架的整合上非常灵活。 在Spring中,bean的注入与装配是核心概念之一,有多种方式可以实现,例如XML...