Spring管理Bean(xml)-IOC

Spring中的一大核心概念是IOC(Inversion of Control,控制反转),简单来说IOC就是统一管理应用程序中的bean对象。IOC负责创建、配置和管理Bean对象的生命周期,以及处理bean之间的依赖关系。在传统web开发方式中,需要不断创建对象,完成相应的业务逻辑,而spring则简化了这一过程,spring通过IOC统一管理了bean对象,需要时只需要从ioc中直接取出即可。

xml方式配置Bean

  1. 基础配置bean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    public class Monster {     //bean对象

    private Integer id;
    private String name;
    private String skill;

    public Monster() {
    }

    public Monster(Integer id, String name, String skill) {
    this.id = id;
    this.name = name;
    this.skill = skill;
    }

    public Integer getId() {
    return id;
    }

    public void setId(Integer id) {
    this.id = id;
    }

    public String getName() {
    return name;
    }

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

    public String getSkill() {
    return skill;
    }

    public void setSkill(String skill) {
    this.skill = skill;
    }


    //xml文件中配置bean
    <bean class="com.mhl.spring.bean.Monster" id="monster01">
    <property name="id" value="100"/>
    <property name="name" value="牛魔王"/>
    <property name="skill" value="芭蕉扇"/>
    </bean>

    //获取bean对象
    public void getMonster(){
    ApplicationContext ioc = new ClassPathXmlApplicationContext("beans.xml");
    Monster monster =ioc.getBean("monster01", Monster.class);
    System.out.println(monster.getId());
    }

    【注意】:

    1. 如果没有配置id,系统会默认分配id,分配id的规则是 全类名#0,全类名#1……
    2. 在获取bean对象时,可以通过id,类型或id+类型的方式,通过id获取时,返回的是Object对象,可以强转成Monster;用类型获取时,要求ioc容器中只能有一个同一个类的bean;用id+类型的方式则可以直接返回bean类型的对象。
  2. 通过构造器配置bean

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!-->index为构造器参数的位置<-->
    <bean class="com.mhl.spring.bean.Car" id="car03">
    <constructor-arg value="001" index="0"/>
    <constructor-arg value="奔驰" index="1"/>
    <constructor-arg value="330000" index="2"/>
    </bean>

    <!-->type为构造器参数的类型<-->
    <bean class="com.mhl.spring.bean.Car" id="car04">
    <constructor-arg value="002" type="java.lang.Integer"/>
    <constructor-arg value="小米SU7" type="java.lang.String"/>
    <constructor-arg value="219800" type="java.lang.String"/>
    </bean>
  3. 通过p名称空间配置bean

    1
    2
    3
    4
    5
    <bean class="com.mhl.spring.bean.Car" id="car02"
    p:id="002"
    p:name="宝马"
    p:price="300000"
    />

    【注意】使用p名称空间时,需要在xml文件上配置xmlns:p=”http://www.springframework.org/schema/p

  4. bean对象之间的相互引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!-->先创建memberDAOImpl,再创建memberDAO<-->
    <bean id="memberDAOImpl" class="com.hspedu.spring.dao.MemberDAOImpl"/>
    <bean id="memberServiceImpl" class="com.hspedu.spring.service.MemberServiceImpl">
    <property name="memberDAO" ref="memberDAOImpl"/>
    </bean>

    <!-->如果按照以下配置,会先创建 department01 对象,再创建 student01 对象.<-->
    <bean id="student01" class="com.hspedu.bean.Student" depends-on="department01"/>
    <bean id="department01" class="com.hspedu.bean.Department" />

    <!-- 引用/注入内部 bean 对象, 直接在配置 bean 时注入-->
    <bean id="memberServiceImpl02"
    class="com.hspedu.spring.service.MemberServiceImpl">
    <property name="memberDAO">
    <bean class="com.hspedu.spring.dao.MemberDAOImpl"/>
    </property>
    </bean>

    【注意】如果存在对象间的相互引用,spring会先将所需对象都创建出来,然后再引用

  5. bean对象的集合/数组类型赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    <!-- 给集合属性注入值-->
    <bean id="master01" class="com.hspedu.spring.beans.Master">
    <property name="name" value="太上老君"/>
    <!-- 给 bean 对象的 list 集合赋值 -->
    <property name="monsterList">
    <list>
    <ref bean="monster03"/>
    <ref bean="monster02"/>
    </list>
    </property>

    <!-- 给 bean 对象的 map 集合赋值 -->
    <property name="monsterMap">
    <map>
    <entry>
    <key>
    <value>monsterKey01</value>
    </key>
    <ref bean="monster01"/>
    </entry>
    <entry>
    <key>
    <value>monsterKey02</value>
    </key>
    <ref bean="monster02"/>
    </entry>
    </map>
    </property>

    <!-- 给 bean 对象的 properties 集合赋值 -->
    <property name="pros">
    <props>
    <prop key="k1">Java 工程师</prop>
    <prop key="k2">前端工程师</prop>
    <prop key="k3">大数据工程师</prop>
    </props>
    </property>

    <!-- 给 bean 对象的数组属性注入值 -->
    <property name="monsterName">
    <array>
    <value>银角大王</value>
    <value>金角大王</value>
    </array>
    </property>

    <!-- 给 bean 对象的 set 属性注入值 -->
    <property name="monsterSet">
    <set>
    <!-- 引用方式-->
    <ref bean="monster01"/>
    <!--内部bean方式-->
    <bean class="com.hspedu.spring.beans.Monster">
    <property name="monsterId" value="10"/>
    <property name="name" value="玉兔精"/>
    <property name="skill" value="钻地洞"/>
    </bean>
    </set>
    </property>
    </bean>
  6. 通过util名称空间创建list

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <util:list id="myListBook">
    <value>三国演义</value>
    <value>西游记</value>
    <value>红楼梦</value>
    <value>水浒传</value>
    </util:list>

    <bean id="bookStore" class="com.hspedu.spring.beans.BookStore">
    <property name="bookList" ref="myListBook"/>
    </bean>
    <!-- bookList为list -->

    【注意】使用util名称空间时,需要在xml文件上配置xmlns:util=”http://www.springframework.org/schema/util

  7. 级联属性赋值

    (级联属性赋值即给对象的属性的属性赋值)

    1
    2
    3
    4
    5
    6
    7
    <bean id="emp" class="com.hspedu.spring.beans.Emp">
    <property name="name" value="jack"/>
    <property name="dept" ref="dept"/>
    <property name="dept.name" value="Java 开发部"/>
    </bean>

    <bean id="dept" class="com.hspedu.spring.beans.Dept"/>
  8. bean配置信息重用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- 继承的方式来实现 bean 配置信息的重用 -->
    <bean id="monster10" class="com.hspedu.spring.beans.Monster">
    <property name="monsterId" value="10"/>
    <property name="name" value="蜈蚣精"/>
    <property name="skill" value="蜇人"/>
    </bean>

    <!-- parent="monster10" 就是继承使用了 monster10 的配置信息 -->
    <bean id="monster11" class="com.hspedu.spring.beans.Monster"
    parent="monster10"/>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!-- 当我们把某个bean设置为 abstract="true" 这个bean只能被继承, 而不能实例化了 -->
    <bean id="monster12" class="com.hspedu.spring.beans.Monster" abstract="true">
    <property name="monsterId" value="12"/>
    <property name="name" value="美女蛇"/>
    <property name="skill" value="吃人"/>
    </bean>

    <!-- parent="monster12" 就是继承使用了 monster12 的配置信息 -->
    <bean id="monster13" class="com.hspedu.spring.beans.Monster"
    parent="monster12"/>
  9. bean对象的单例和多例

    【注意】:

    1. 在 spring 的 ioc 容器, 在默认情况下是安照单例创建的, 即配置一个 bean 对象后,ioc 容器只会创建一个 bean 实例。
    2. 如果,我们希望 ioc 容器配置的某个 bean 对象,是以多个实例形式创建的则可以通过配置 scope=”prototype” 来指定 。
    3. 默认是单例 singleton, 在启动容器时, 默认就会创建 , 并放入到 singletonObjects 集合 。
    4. <bean scope="prototype" > 设置为多实例机制后, 该 bean 是在 getBean()时才创
      建 。
    5. 如 果 是 单 例 singleton, 同 时 希 望 在 getBean 时 才 创 建 , 可 以 指 定 懒 加 载
      lazy-init=”true” (注意默认是 false,空间换时间)
    1
    <bean name="car" scope="prototype" class="com.hspedu.spring.beans.Car"/>
  10. bean的生命周期

    【注意】

    1. 执行构造器
    2. 执行 set 相关方法
    3. 调用 bean 的初始化的方法(需要配置)
    4. 使用 bean
    5. 当容器关闭时候, 调用 bean 的销毁方法(需要配置)
    1
    2
    3
    4
    5
    <!-- 配置 bean 的初始化方法和销毁方法 -->
    <bean id="house" class="com.hspedu.spring.beans.House" init-method="init"
    destroy-method="destory">
    <property name="name" value="北京豪宅"/>
    </bean>
  11. 配置bean的后置处理器

    • bean的后置处理器 是在bean初始化方法前和初始化调用后被调用
    • 可以对容器内所有对象进行统一处理,比如日志处理/权限的校验/安全的验证/事务的管理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
    * 什么时候被调用: 在Bean的init方法前被调用
    * @param bean 传入的在IOC容器中创建/配置Bean
    * @param beanName 传入的在IOC容器中创建/配置Bean的id
    * @return Object 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回
    * @throws BeansException
    */

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessBeforeInitialization().. bean="
    + bean + " beanName=" + beanName);

    //初步体验案例: 如果类型是House的统一改成 上海豪宅
    //对多个对象进行处理/编程==>切面编程
    if(bean instanceof House) {
    ((House)bean).setName("上海豪宅~");
    }
    return null;
    }

    /**
    * 什么时候被调用: 在Bean的init方法后被调用
    * @param bean 传入的在IOC容器中创建/配置Bean
    * @param beanName 传入的在IOC容器中创建/配置Bean的id
    * @return 程序员对传入的bean 进行修改/处理【如果有需要的话】 ,返回
    * @throws BeansException
    */

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessAfterInitialization().. bean="
    + bean + " beanName=" + beanName);
    return bean;
    }
    }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!-- 配置 bean 的初始化方法和销毁方法 -->
    <bean id="house" class="com.hspedu.spring.beans.House" init-method="init"
    destroy-method="destory">
    <property name="name" value="北京豪宅"/>
    </bean>

    <!-- bean 后置处理器的配置 -->
    <bean id="myBeanPostProcessor" class="com.hspedu.spring.beans.MyBeanPostProcessor" />
    </beans>
  12. 通过属性文件给bean注入值

    1
    2
    3
    4
    //.properties
    name=\u9EC4\u888D\u602A
    id=10
    skill=\u72EE\u5B50\u543C
    1
    2
    3
    4
    5
    6
    <context:property-placeholder location="classpath:my.properties"/>
    <bean id="monster100" class="com.hspedu.spring.beans.Monster">
    <property name="monsterId" value="${id}"/>
    <property name="name" value="${name}"/>
    <property name="skill" value="${skill}"/>
    </bean>

    【注意】使用context名称空间时,需要在xml文件上配置xmlns:context=”http://www.springframework.org/schema/context

配置bean的方式还有很多,就不再一一列举,后期主要是通过注解方式配置,xml作为了解即可。