04.spring-ioc-XML方式管理Bean

153 阅读5分钟

前言

Bean(汉译咖啡豆). 又称JAVA Bean.其实就是JAVA程序中的一个个对象,所以Bean的管理其实就是spring对于JAVA程序中的对象的管理。Spring中提供了两种方式来管理Bean:

  • 基于XML方式的Bean管理
  • 基于注解方式的Bean管理

本节主要讲述XML方式管理Bean。

基于XML方式的Bean管理

1. bean的属性标签

<bean id="user1" class="com.mayuanfei.springioc.User" name="user11" lazy-init="true" scope="prototype"/>
属性名含义
id对象的id
class类的全路径名
name和id功能类似,也是用于获得该bean
lazy-init懒加载,默认false。 true:调用getBean的时候再去实例化对象
scope控制对象单例多例和使用范围
1. singleton(默认值):Spring容器中只会存在一个共享的bean实例
2. prototype:每一次获取都会产生一个新的bean实例,相当与一个new的操作
3. request:表示针对每一次HTTP请求都会产生一个新的bean,
同时该bean仅在当前HTTP request内有效
4. session:作用域表示针对每一次HTTP请求都会产生一个新的bean,
同时该bean仅在当前HTTP session内有效
5. global session:类似于标准的HTTP Session作用域,不过它仅仅在
基于portlet的web应用中才有意义

注意:

上面的<bean id="user"... 表示调用User类的默认构造方法。如果该方法中没有默认构造方法,则报错。

2. 通过Set方法给对象赋值

<bean id="user2" class="com.mayuanfei.springioc.User" lazy-init="true">
    <property name="userId" value="1"/>
    <property name="userName" value="老马"/>
    <property name="address" value="北京朝阳"/>
</bean>

3. 通过构造方法给对象赋值

<!--
 constructor-arg 使用构造方法实现依赖注入
 constructor-arg 的个数必须和某个构造方法的参数个数相对应
 -name:指的是参数名
 -index:指的是参数的索引
 -value:指的是参数值
 -->
<bean id="user3" class="com.mayuanfei.springioc.User" lazy-init="true">
    <constructor-arg name="userId" value="3"/>
    <constructor-arg name="userName" value="老马3"/>
    <constructor-arg name="address" value="北京顺义3"/>
</bean>
<bean id="user33" class="com.mayuanfei.springioc.User" lazy-init="true">
    <constructor-arg index="0" value="33"/>
    <constructor-arg index="1" value="老马33"/>
    <constructor-arg index="2" value="北京顺义33"/>
</bean>

4. 通过p名称空间和c名称空间给对象赋值

  • 添加约束

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    

    这里的xmlns:p和xmlns:c就是新加入的命名空间。

  • 进行配置

    <!--
    p名称空间,就是对property的简化处理
    c名称空间,就是对constructor-arg的简化
    -->
    <bean id="user4" class="com.mayuanfei.springioc.User" lazy-init="true"
       p:userId="4" p:userName="老马4" p:address="北京朝阳4"/>
    <bean id="user44" class="com.mayuanfei.springioc.User" lazy-init="true"
       c:userId="44" c:userName="老马44" c:address="北京朝阳44"/>
    

5. 注入特殊字符

<!--
null值注入和特殊字符注入
& : &amp;
< : &lt;
> : &gt;
-->
<bean id="user5" class="com.mayuanfei.springioc.User" lazy-init="true">
    <property name="userId">
        <null/>
    </property>
    <property name="userName" value="老马5&amp;&lt;&gt;"/>
    <property name="address">
        <value><![CDATA[北京顺义5&<>]]></value>
    </property>
</bean>

6. Bean引用

<bean id="book6" class="com.mayuanfei.springioc.Book" lazy-init="true">
    <property name="bookName" value="04.spring-ioc-Bean管理"/>
    <property name="author" ref="user5"/>
</bean>

7. 各种集合注入

  • 添加约束

    image-20230209134223945
  • 进行配置

    <!-- 集合注入 -->
     <bean id="student7" class="com.mayuanfei.springioc.Student" lazy-init="true">
         <!--数组属性注入-->
         <property name="books">
             <array>
                 <value>01.spring简介</value>
                 <value>02.spring-ioc概念</value>
                 <value>03.spring-ioc实现原理</value>
             </array>
         </property>
         <!--set集合注入-->
         <property name="bookSet">
             <set>
                 <value>01.spring简介</value>
                 <value>02.spring-ioc概念</value>
                 <value>03.spring-ioc实现原理</value>
             </set>
         </property>
         <!--list集合注入-->
         <property name="bookList">
             <list>
                 <value>01.spring简介</value>
                 <value>02.spring-ioc概念</value>
                 <value>03.spring-ioc实现原理</value>
             </list>
         </property>
         <!--map集合注入-->
         <property name="bookMap">
             <map>
                 <entry key="01.spring简介" value="老马"/>
                 <entry key="02.spring-ioc概念" value="老马"/>
                 <entry key="03.spring-ioc实现原理" value="老马"/>
             </map>
         </property>
         <!--List对象集合注入-->
         <property name="bookList2" ref="publicbookList"/>
     </bean>
    
     <!--定义公共集合-->
     <util:list id="publicbookList">
         <!--声明多个Book对象-->
         <bean id="b1" class="com.mayuanfei.springioc.Book" p:bookName="01.spring简介" p:author-ref="user5"/>
         <bean id="b2" class="com.mayuanfei.springioc.Book" p:bookName="02.spring-ioc概念" p:author-ref="user4"/>
         <bean id="b3" class="com.mayuanfei.springioc.Book" p:bookName="03.spring-ioc实现原理" p:author-ref="user3"/>
     </util:list>
    

8. 工厂方式创建对象

  • 继承AbstractFactoryBean类

    核心思路就是实现FactoryBean来创建具体的实例对象,可以实现FactoryBean的虚基类AbstractFactoryBean类实现。代码如下:

    public class BookFacotry extends AbstractFactoryBean<Book> {
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    
        @Override
        protected Book createInstance() throws Exception {
            Book book = new Book();
            book.setBookName("01.spring简介");
            book.setAuthor(new User("user8", "老马8", "北京顺义8"));
            return book;
        }
    }
    

    继承关系如下:

    image-20230209153612800

  • 配置文件

    <!-- 工厂方式创建对象 -->
    <bean id="book8" class="com.mayuanfei.springioc.BookFacotry"/>
    

9. 自动注入

  • 配置文件

    <bean id="author" class="com.mayuanfei.springioc.User" >
        <property name="userId" value="1"/>
        <property name="userName" value="老马"/>
        <property name="address" value="北京朝阳"/>
    </bean>
    
    <bean id="book" class="com.mayuanfei.springioc.Book" autowire="byName" >
        <property name="bookName" value="java设计模式"/>
    </bean>
    

    autowire可以使容器中管理的对象自动注入到当前对象中,它有byName和byType两种方式。

    • byName

      byName 根据目标id值和属性值注入,要保证当前对象的属性值和目标对象的id值一致,比如这里User之所以id为author,是因为Book类中定义作者的变量名为:author

      @Data
      public class Book {
          /**
           * 书籍名称
           */
          private String bookName;
      
          /**
           * 作者
           */
          private User author;
      }
      
    • byType

      根据类型注入,要保证相同类型的目标对象在容器中只有一个实例。此时可以不用在意id起的名字了。

10. 读取外部属性文件

spring容器可以读取.properties属性配置文件,可以将文件中的信息注入给bean

  • 增加context名称空间

    image-20230214134832872
  • 修改配置

    <!-- 这里注意文件编码格式的设置,否则很容易出现乱码 -->
    <context:property-placeholder location="classpath:user.properties" 
                                  file-encoding="utf-8"/>
    <!-- User对象的属性值通过属性文件中的值来设置 -->
    <bean id="user" class="com.mayuanfei.springioc.User" >
        <property name="userId" value="${user.userId}"/>
        <property name="userName" value="${user.userName}"/>
        <property name="address" value="${user.address}"/>
    </bean>
    

11. 代码地址

gitee.com/mayuanfei/S… 下的SpringIoc03

记忆印记

  • spring容器默认会在容器启动时就会去创建对象,而如果不想这样可以用lazy-init="true" 来解决
  • Spring容器内的对象默认都是单例的,如果希望每次new出新对象可以用scope=prototype来解决
  • 通过property来调用set方法设置属性值;通过constructor-arg来调用构造方法设置属性值
  • 特殊字符记得用转义符
  • bean的引用采用ref来指定
  • 自动注入有byName和byType两种类型
  • 可以通过属性文件来设置对象属性值