Spring知识一(bean配置)

IOC与DI概念

IOC(Inversion of Control):其思想是反转资源获取的方向. 传统的资源查找方式要求组件向容器发起请求查
找资源. 作为回应, 容器适时的返回资源. 而应用了 IOC 之后, 则是容器主动地将资源推送给它所管理的组件, 组件所要做的仅是选择一种合适的方式来接受资源. 这种行为也被称为查找的被动形式。
DI(Dependency Injection) — IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接。

bean配置,ApplicationContext.xml中配置


<!-- 配置一个 bean 
    id为在代码中引用的名称,唯一,且可以为多个,利用逗号、分号、或空格分隔
    class执向全类名,spring就是根据全类名,通过反射生成一个实例对象,id为这个实例对象的引用,所以我们必须在这个类中添加默认的构造方法,并且属性要有setter方法
-->
<bean id="user" class="com.wf.springbean.User">
        <property name="name" value="tom"></property>
        <property name="sex" value="boy"></property>
    </bean>

加载配置文件,获取bean

在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用。

Spring 两种类型的 IOC 容器实现—重点

1.BeanFactory: IOC 容器的基本实现.
2.ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口,可以根据不同的实现类,去加载配置文件。
注意:BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory。

ApplicationContext 的主要实现类:
ClassPathXmlApplicationContext:从 类路径下加载配置文件
FileSystemXmlApplicationContext: 从文件系统中加载配置文件
ConfigurableApplicationContext :扩展于 ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让 ApplicationContext 具有启动、刷新和关闭上下文的能力
ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。【加载配置文件时】
WebApplicationContext 是专门为 WEB 应用而准备的,它允许从相对于 WEB 根目录的路径中完成初始化工作

//1. 创建 Spring 的 IOC 容器 
//2. ClassPathXmlApplicationContext为一个接口,ClassPathXmlApplicationContext是其中的一个实现类
//3. ClassPathXmlApplicationContext 是根据classpath路径进行加载
ClassPathXmlApplicationContext cxt = new ClassPathXmlApplicationContext("ApplicationContext.xml");

        // 1. 利用getBean方法获取容器中bean实例
        User  user = (User) cxt.getBean("user");
        /*
         根据类型来获取 bean 的实例: 要求在  IOC 容器中只有一个与之类型匹配的 bean, 若有多个则会抛出异常. 建议使用id进行匹配
        一般情况下, 该方法可用, 因为一般情况下, 在一个 IOC 容器中一个类型对应的 bean 也只有一个. 
        HelloWorld helloWorld1 = ctx.getBean(HelloWorld.class);
        */

        // 1. 调用方法
        System.out.println(user.say());
        System.out.println(user);

依赖注入的方式—重点

属性注入(最常用,记住)
构造器注入(一般用,了解)
工厂方法注入(很少使用,不推荐,可以忘记)

属性注入:
属性注入即通过 setter 方法注入Bean 的属性值或依赖的对象,使用 元素, 使用 name 属性指定 Bean 类的属性名称,value 属性或 子节点指定属性值。【在这里,注入是根据setter方法来的而不是属性名称,但是一般我们都是直接生成setter方法,而不去更改这个名称,所以就是说成name为属性名称】

<bean id="user" class="com.wf.springbean.User">
        <property name="name" value="tom"></property>
        <property name="sex" value="boy"></property>
</bean>

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

<bean id="user01" class="com.wf.springbean.User">
        <!-- 要求: 在 Bean 中必须有对应的构造器.  -->
        <constructor-arg value="Mike" name="name"></constructor-arg>
        <constructor-arg value="girl" name="sex"></constructor-arg>
</bean>

    <!-- 若一个 bean 有多个构造器, 如何通过构造器来为 bean 的属性赋值 -->
    <!-- 可以根据 index(参数位置) 和 value 进行更加精确的定位. (了解) -->
    <bean id="car" class="com.wf.springbean.Car">
        <constructor-arg value="KUGA" index="1"></constructor-arg>
        <constructor-arg value="ChangAnFord" index="0"></constructor-arg>
        <constructor-arg value="250000" type="float"></constructor-arg>
    </bean>

    <bean id="car2" class="com.wf.springbean.Car">
        <constructor-arg value="ChangAnMazda"></constructor-arg>
        <!-- 若字面值中包含特殊字符, 则可以使用 DCDATA 来进行赋值. (了解) -->
        <constructor-arg>
            <value><![CDATA[<ATARZA>]]></value>
        </constructor-arg>
        <constructor-arg value="180" type="int"></constructor-arg>
    </bean>

引用其它 Bean—重点

组成应用程序的 Bean 经常需要相互协作以完成应用程序的功能. 要使 Bean 能够相互访问, 就必须在 Bean配置文件中指定对 Bean 的引用。
在 Bean 的配置文件中, 可以通过 【ref】 元素或 【ref】 属性为 Bean 的属性或构造器参数指定对 Bean 的引用。
也可以在属性或构造器里包含 Bean 的声明, 这样的 Bean 称为内部 Bean。当 Bean 实例仅仅给一个特定的属性使用时, 才将其声明为内部 Bean. 内部 Bean 声明直接包含在 【property】 或【constructor-arg】 元素里, 不需要设置任何 id 或 name 属性,内部 Bean 不能使用在任何其他地方。

<!-- 引用其他bean -->

<bean id="company" class="com.wf.springbean.Person">
<property name="name" value="longchuang"></property>
<property name="car" ref="car"></property>
<!--        <property name="car">
        <ref bean="car"/> 
        </property> 
-->
</bean>
<!-- 使用内部bean,不能被外部访问-->
<bean id="company01" class="com.wf.springbean.Person">
    <property name="name" value="dazhong"></property>
    <property name="car">
        <bean class="com.wf.springbean.Car">
        <constructor-arg value="KUGA001" ></constructor-arg>
        <constructor-arg value="ChangAnFord001" ></constructor-arg>
        <constructor-arg value="250000" type="float"></constructor-arg>
        </bean>
    </property>
</bean>

注入参数详解:null 值和级联属性—了解

可以使用专用的 【null】 元素标签为 Bean 的字符串或其它对象类型的属性注入 null 值
和 Struts、Hiberante 等框架一样,Spring 支持级联属性的配置。不建议使用级联属性这样赋值,这样的赋值,会覆盖掉前面的bean中的此属性的值

<!-- null测试及级联属性  利用构造注入时,必须保证构造函数-->

<bean id="person02" class="com.wf.springbean.Person">
    <constructor-arg name="name" value="jack"></constructor-arg>
    <!-- <constructor-arg name="car" ><null/></constructor-arg> -->
    <constructor-arg name="car" ref="car"></constructor-arg>
     <property name="car.maxSpeed" value="251"></property> 
<!-- 这种方式的赋值会将ref关联的car的maxSpeed属性进行更改。这样的话,只要有涉及到car的都会更改-->
</bean>

集合属性的配置—重点

在 Spring中可以通过一组内置的 xml 标签(例如: 【list】, 【set】 或 【map】) 来配置集合属性.
配置 java.util.List 类型的属性, 需要指定 【list】 标签, 在标签里包含一些元素. 这些标签可以通过 【value】 指定简单的常量值, 通过 【ref】 指定对其他 Bean 的引用. 通过【bean】 指定内置 Bean 定义. 通过 【null/】 指定空元素. 甚至可以内嵌其他集合.
数组的定义和 List 一样, 都使用 【list】
配置 java.util.Set 需要使用 【set】 标签, 定义元素的方法与 List 一样.

Java.util.Map 通过 【map】 标签定义, 【map】 标签里可以使用多个 【entry】 作为子标签. 每个条目包含一个键和一个值.
必须在 【key】 标签里定义键
因为键和值的类型没有限制, 所以可以自由地为它们指定 【value】, 【ref】, 【bean】 或 【null】 元素.
可以将 Map 的键和值作为 【entry】 的属性定义: 简单常量使用 key 和 value 来定义; Bean 引用通过 key-ref 和 value-ref 属性定义

使用 【props】 定义 java.util.Properties, 该标签使用多个 【prop】 作为子标签. 每个 【prop】 标签必须定义 key 属性,在整合hibernate时,会利用这个属性

<!-- list 集合配置 -->      
<bean id="person" class="com.wf.springcollection.Person">
    <property name="name" value="rose"></property>
    <property name="cars">  
        <list>
            <ref bean="car1"/>
            <ref bean="car2"/>
            <ref bean="car3"/> 
            <bean class="com.wf.springcollection.Car">
                    <property name="company" value="tutu04"></property>
                    <property name="brand" value="HaFu04"></property>
                    <property name="maxSpeed" value="254"></property>
                    <property name="price" value="25400"></property>
        </bean> 
        </list>
    </property>
</bean>     

<!-- map集合配置 -->
<bean id="personmap" class="com.wf.springcollection.Person">
    <property name="name" value="jack"></property>
    <property name="mapscars">
        <map>
            <entry key="AA" value-ref="car1"></entry>
            <entry key="BB" value-ref="car2"></entry>
            <entry key="CC" value-ref="car3"></entry>
        </map>
    </property>
</bean>

<!-- prop配置,在整合hibernate使用 -->
<bean id="datasource" class="com.wf.springcollection.DataSource">
    <property name="properties">
    <props>
        <prop key="user">root</prop>
        <prop key="psaaword">1234</prop>
        <prop key="jbbcUrl">jdbc:mysql:///test</prop>
        <prop key="driverClass">com.mysql.jdbc.Driver</prop>
     </props>   

 </property>
</bean>


<!-- 将集合属性进行单独配置,这样的话可以供多个bean使用,需要引入命名空间util -->
<util:list id="carslist">
        <ref bean="car1"/>
        <ref bean="car2"/>
</util:list>

<bean id="personlist" class="com.wf.springcollection.Person">
    <property name="name" value="jack"></property>
    <property name="cars" ref="carslist"></property>
</bean>


<!--p:命名空间的使用,可以简化属性配置  -->
<bean id="personp" class="com.wf.springcollection.Person"
p:name="Queen" p:cars-ref="carslist">

</bean>

自动装配配置—了解

Spring IOC 容器可以自动装配 Bean. 需要做的仅仅是在 【bean】 的 autowire 属性里指定自动装配的模式。
1、byName(根据名称自动装配): 必须将目标 Bean 的名称和属性名设置的完全相同。
2、byType(根据类型自动装配): 若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配。报错。利用注解时,会用到bytype。
3、constructor(通过构造器自动装配): 当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用。

自动装配的缺点:
在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性. 然而, 若只希望装配个别属性时, autowire 属性就不够灵活了.
autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.
一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些


<!--正常配置  -->
<bean id="user" class="com.wf.springauto.User">
    <property name="name" value="zhangsan"></property>
    <property name="car" ref="car"></property>
    <property name="address" ref="address"></property>

</bean>


<!-- 根据Name进行匹配。根据bean类的名字和当前setter风格的属性名称进行自动匹配 ,都是用在bean与bean之间的关联中-->
<bean id="userautoname" class="com.wf.springauto.User" autowire="byName">
    <property name="name" value="zhangsan"></property>
        <!-- <property name="car" ref="car"></property>
        <property name="address" ref="address"></property> -->
</bean>

<!-- 根据type进行匹配。根据bean类的类型和bean的属性类型进行自动装配,都是用在bean与bean之间的关联中-->
<bean id="userautotype" class="com.wf.springauto.User" autowire="byType">
    <property name="name" value="zhangsan"></property>
        <!-- <property name="car" ref="car"></property>
        <property name="address" ref="address"></property> -->
</bean>

现在的项目一般都是利用注解进行配置,因为注解的方式可以大大缩减代码量。但是在一些全局的属性配置中,利用xml的配置还是比较方便。

源码可以在我的资源中查看 或者 github地址:https://github.com/wangfa1994/SpringLearning/tree/spring001

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章