Spring的IoC容器

Spring是一个轻量级的Java开发框架,其提供的两大基础功能为IoC和AOP,其中IoC为依赖反转(Inversion of Control)。IOC容器的基本理念就是“为别人服务”,那为别人服务什么呢?其中最重要就是业务对象的构建管理和业务对象之间的依赖绑定。java

  • 业务对象的构建管理:业务场景中,无需关心业务对象如何建立、如何管理,在须要时只需获取便可。业务对象的构建管理交给IoC容器,避免这部分代码对业务逻辑的侵染。
  • 业务对象之间的依赖绑定:IoC容器须要先了解业务对象之间的依赖关系,这样依据以前业务对象的构建管理就能够对外提供IoC服务,保证每一个业务对象在使用时处于就绪状态。

IoC容器管理业务对象,首先须要知道业务对象之间的依赖关系,如下有几种方式告诉IoC容器其管理的对象之间的绑定关系:spring

  • 能够经过简单的文本方式记录被注入对象和其依赖对象的对应关系。
  • 使用描述性更强的XML文件格式记录对象之间的对应关系。
  • 还能够经过编写代码的方式(调用IoC容器提供的对应API)设置对象之间的关系。
  • ...

注意:无论是什么方式来告知IoC容器对象之间的绑定关系,最终都是须要经过编码方式来将这些信息"写入"到IoC容器中的。session

一个XML配置方式的示例:框架

<!-- 配置bean,属性配置方式 -->
<bean id="helloWorld"  class="com.luo.testspring.HelloWorld" scope="singleton">
    <property name="name" value="spring"/>
</bean>

 

Spring的IoC容器提供两种基本的容器类型:BeanFactory和ApplicationContext。测试

  • BeanFactory:基础类型IoC容器,提供基本的容器服务,若是没有特殊指定,采用延迟初始化策略,也就是当客户端须要容器中某个对象时,才对该受管理的对象初始化及其依赖注入操做。因此,相对来讲,BeanFactory容器启动较快,所需资源有限,对于资源有限,而且功能要求不严格的场景,使用BeanFactory容器是比较合适的。
  • ApplicationContext:ApplicationContext是在BeanFactory基础之上构建的,是一个比较高级的容器,除了拥有BeanFactory的所有功能外,也提供其余高级特性,好比事件发布、国际化信息支持等。ApplicationContext所管理的对象,默认ApplicationContext启动以后所有初始化并绑定完成,因此其启动较慢,占用资源较多。在系统资源充足,并须要提供较多功能的使用场景,ApplicationContext是一个不错的选择。

 

BeanFactory使用示例(XML配置方式):this

/* HelloWolrd类,待依赖注入的类 */
public class HelloWorld {
    private String name;

    public HelloWorld() {
    }

    public HelloWorld(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void hello() {
        System.out.println("hello: " + this.name);
    }
}
<!-- springConfig.xml配置文件Bean配置 -->

<!-- 配置bean,属性配置方式 -->
<bean id="helloWorld"  class="com.luo.testspring.HelloWorld" scope="singleton">
    <property name="name" value="spring"/>
</bean>

<!-- 经过构造方法配置bean属性 -->
<bean id="helloWorld2" class="com.luo.testspring.HelloWorld">
    <constructor-arg value="spring2" index="0"></constructor-arg>
</bean>

<bean id="helloWorld3" class="com.luo.testspring.HelloWorld">
    <property name="name">
        <bean class="java.lang.String">
            <constructor-arg value="spring3"/>
        </bean>
    </property>
</bean>
/* 测试代码 */
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("springConfig.xml"));

HelloWorld helloWorld = (HelloWorld) factory.getBean("helloWorld");
helloWorld.hello();

HelloWorld helloWorld2 = factory.getBean("helloWorld2", HelloWorld.class);
helloWorld2.hello();

HelloWorld helloWorld3 = factory.getBean("helloWorld3", HelloWorld.class);
helloWorld3.hello();

 

ApplicationContext使用示例(XML配置方式):编码

/* 测试代码 */
HelloWorld helloWorld = (HelloWorld) ctx.getBean("helloWorld");
helloWorld.hello();

HelloWorld helloWorld2 = ctx.getBean("helloWorld", HelloWorld.class);
helloWorld2.hello();

HelloWorld helloWorld3 = ctx.getBean("helloWorld3", HelloWorld.class);
helloWorld3.hello();

 

依赖注入的3种方式spa

  • 构造方法注入:调用被注入对象的构造方然注入,优势是对象在构造完成就进入了就绪状态。
  • 属性注入:调用被注入对象的setter/getter方法。
  • 接口注入:如今不提倡的一种方式,由于它强制被注入对象实现没必要要的接口,带有侵入性。

 

spring的bean配置(XML配置方式)prototype

属性注入即经过 setter 方法注入Bean 的属性值或依赖的对象,使用 <property> 元素, 使用 name 属性指定 Bean 的属性名称,value 属性或 <value> 子节点指定属性值,属性注入是实际应用中最经常使用的注入方式。属性注入Bean类须有一个默认的构造方法。3d

<!-- Hello类中有一个String类型的msg属性 -->
<bean id="hello" class="com.luoxn28.Hello">
    <property name="msg" value="luoxn28"/>
</bean>

经过构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可使用,构造器注入在 <constructor-arg> 元素里声明属性。

<bean id="msg" class="java.lang.String">
    <constructor-arg value="string"/>
</bean>
<!-- 按照索引匹配入参 -->
<bean id="car" class="com.luoxn28.Car">
    <constructor-arg value="比亚迪" index="0"/>
    <constructor-arg value="中国制造" index="1"/>
    <constructor-arg value="200000" index="2"/>
</bean>
<!-- 按照类型匹配入参 -->
<bean id="car2" class="com.luoxn28.Car">
    <constructor-arg value="比亚迪" type="java.lang.String">
    <constructor-arg value="中国制造" type="java.lang.String"/>
    <constructor-arg value="200000" type="double"/>
</bean>

组成应用程序的 Bean 常常须要相互协做以完成应用程序的功能。要使 Bean 可以相互访问,就必须在 Bean 配置文件中指定对 Bean 的引用,在 Bean 的配置文件中,能够经过 <ref> 元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用。也能够在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean。

<bean id="msg" class="java.lang.String">
    <constructor-arg value="luoxn28"/>
</bean>

<!-- Hello类中有一个String类型的msg属性 -->
<bean id="hello" class="com.luoxn28.Hello">
    <property name="msg" ref="msg"/>
</bean>

当 Bean 实例仅仅给一个特定的属性使用时,能够将其声明为内部 Bean,内部 Bean 声明直接包含在 <property> 或 <constructor-arg> 元素里,不须要设置任何 id 或 name 属性。内部 Bean 不能使用在任何其余地方。

<!-- Hello类中有一个String类型的msg属性 -->
<bean id="hello" class="com.luoxn28.Hello">
    <property name="msg">
        <bean class="java.lang.String">
            <constructor-arg value="luoxn28"/>
        </bean>
    </property>
</bean>

能够经过一组内置的 xml 标签(例如: <list>, <set> 或 <map>) 来配置集合属性。

<!-- CollectionClass类有3个属性,List<String> list、Set<String> set、Map<String, String> map-->
<bean id="collectionClass" class="com.luoxn28.CollectionClass">
    <property name="list">
        <list>
            <value>luoxn28</value>
            <value>luoxn29</value>
            <value>luoxn30</value>
        </list>
    </property>
    <property name="set">
        <set>
            <value>luoxn28</value>
            <value>luoxn29</value>
            <value>luoxn30</value>
        </set>
    </property>
    <property name="map">
        <map>
            <entry key="str1" value="luoxn28"/>
            <entry key="str2"><value>luoxn29</value></entry>
            <entry key="str3"><value>luoxn30</value></entry>
        </map>
    </property>
</bean>

 

Bean的做用域

Spring最初提供两种bean的scope类型:singleton和prototype,在发布2.0以后,新增了request、session和global session类型,不过这3种新增的只能用在Web应用中。能够经过bean属性scope来指定bean的scope类型,若是是singleton类型的话,在用户获取该bean以后,容器仍是会接管该bean的生命周期;若是是prototype的话,在用户获取该bean以后,容器就不接管该bean了,也就是容器每次会建立一个新的bean对象返回给用户。

<!-- Hello对象每次获取都会新建 -->
<bean id="hello" class="com.luoxn28.Hello" scope="prototype">
    <property name="msg" value="luoxn28"/>
</bean>

 

经过静态方法建立bean

调用静态工厂方法建立 Bean是将对象建立的过程封装到静态方法中,当用户须要对象时,只须要简单地调用静态方法,而不一样关心建立对象的细节。要声明经过静态方法建立的 Bean, 须要在 Bean 的 class 属性里指定拥有该工厂的方法的类, 同时在 factory-method 属性里指定工厂方法的名称. 最后, 使用 <constrctor-arg> 元素为该方法传递方法参数。

public static Hello createHello() {
    return new Hello();
}
<bean id="hello" class="com.luoxn28.Hello" factory-method="createHello">
</bean>

 

经过实例方法建立bean

将对象的建立过程封装到另一个对象实例的方法里. 当用户须要请求对象时, 只须要简单的调用该实例方法而不须要关心对象的建立细节。要声明经过实例工厂方法建立的 Bean,在 bean 的 factory-bean 属性里指定拥有该工厂方法的 Bean,在 factory-method 属性里指定该工厂方法的名称,使用 construtor-arg 元素为工厂方法传递方法参数。

相关文章
相关标签/搜索