XML方式配置Spring容器

XML方式配置Spring容器

核心步骤

  1. 导入依赖

  2. 创建Spring配置文件

    • 虽然没有严格的命名规则,通常使用applicationContext.xml作为默认的Spring配置文件名称。
  3. 定义Bean

  4. 配置Bean的依赖

  5. 如果需要使用AOP(面向切面编程),可以在XML配置文件中定义切面、切点和通知

  6. 如果需要使用Spring的事务管理,可以在XML配置文件中定义事务管理器及其相关配置

  7. 加载Spring配置文件

    • 在Java代码中,使用ClassPathXmlApplicationContextFileSystemXmlApplicationContext加载Spring配置文件并初始化Spring容器

    • import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class Main {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
              //根据id获取Bean
              MyBean myBean = (MyBean) context.getBean("myBean");
              //根据类型获取Bean
              MyBean myBean = (MyBean) context.getBean(MyBean.class);
              //根据id和类型获取Bean
              MyBean myBean = (MyBean) context.getBean("myBean",MyBean.class);
              myBean.doSomething();
          }
      }
      

XML配置文件基本结构

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

    

</beans>

一个基础的Spring XML配置文件通常包含以下部分:

  • XML声明:指定XML版本和编码。
  • Spring命名空间:引入Spring的命名空间(如beanscontext等)。
  • Bean定义:定义Spring容器管理的Bean。
  • 依赖注入:通过构造函数或setter方法注入依赖。
  • 注解支持:启用注解扫描,简化配置。
  • 引用外部文件:使用 ${} 占位符引用文件中的属性
<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
           
    <!-- 加载外部属性文件 -->
    <context:property-placeholder location="classpath:config.properties"/>
    
    <!-- 启用注解扫描 -->
    <context:component-scan base-package="com.example" />

    <!-- 定义一个Bean -->
    <bean id="myService" class="com.example.MyServiceImpl">
        <!-- 注入依赖 -->
        <property name="myRepository" ref="myRepository" />
    </bean>

    <!-- 定义另一个Bean -->
    <bean id="myRepository" class="com.example.MyRepositoryImpl" />
</beans>

<context:component-scan> 元素

  • 用于启用注解扫描,自动注册带有@Component@Service@Repository@Controller等注解的类。

  • base-package属性指定扫描的包路径。

    <context:component-scan base-package="com.example" />
    

<import> 元素

  • 用于导入其他配置文件,实现模块化配置。

    <import resource="applicationContext-dao.xml" />
    <import resource="applicationContext-service.xml" />
    

配置文件中的元素

根元素

  • 是所有Spring配置文件的根元素。
  • 通过xmlns引入Spring的命名空间。
  • 通过xsi:schemaLocation指定命名空间的Schema文件位置。

元素

  • 用于定义一个Bean。

  • <bean id="myBean" class="com.example.MyBean" scope="singleton" init-method="init" destroy-method="destroy" />
    
  • 常用属性:

    • id:Bean的唯一标识符。
    • class:Bean的全限定类名。
    • scope:Bean的作用域(如singletonprototype等)。
      • singleton(默认值):
        • 作用: 单例模式。Spring容器中只会创建一个Bean实例,所有对该Bean的请求都会返回同一个实例。
        • 在Bean实例创建并完成依赖注入后,Spring容器会立即调用 init-method 指定的方法,仅调用一次,因为 singleton Bean在容器中只有一个实例
        • 在Spring容器关闭时,Spring会调用 destroy-method 指定的方法,仅调用一次,因为 singleton Bean在容器中只有一个实例
        • 生命周期: Bean实例在Spring容器启动时创建,容器关闭时销毁。
        • 适用场景: 适用于无状态的Bean,例如服务类、工具类等。
      • prototype:
        • 作用: 原型模式。每次请求Bean时,Spring容器都会创建一个新的实例。
        • 每次创建新的Bean实例并完成依赖注入后,Spring容器会调用 init-method 指定的方法,每次创建新实例时都会调用一次
        • Spring容器不会管理 prototype Bean的生命周期,因此 destroy-method 指定的方法不会被自动调用,prototype Bean的生命周期由客户端代码管理,Spring容器只负责创建Bean实例,不负责销毁
        • 生命周期: Bean实例在每次请求时创建,容器不管理其生命周期,即不会调用销毁方法。
        • 适用场景: 适用于有状态的Bean,例如每次请求都需要独立状态的Bean。
    • init-method:指定Bean初始化时调用的方法。
    • destroy-method:指定Bean销毁时调用的方法。
  • init-method

    • 作用: 指定Bean初始化完成后调用的方法。

    • 调用时机: 在Bean的所有依赖注入完成之后,Bean实例已经创建并准备好使用时调用。

    • 方法要求:

      • 方法名由 init-method 属性指定。
      • 方法必须是无参的(即没有参数)。
      • 方法可以是 publicprotectedprivate(如果是 private,Spring会通过反射调用)。
      • 方法返回值类型必须是 void
      public class MyBean {
          public void init() {
              System.out.println("MyBean is initialized!");
          }
      }
      
      <bean id="myBean" class="com.example.MyBean" init-method="init" />
      
  • destroy-method

    • 作用: 指定Bean销毁前调用的方法。

    • 调用时机: 在Spring容器关闭时,或者Bean的作用域结束(例如 singleton Bean在容器关闭时,prototype Bean不会被调用)。

    • 方法要求:

      • 方法名由 destroy-method 属性指定。
      • 方法必须是无参的(即没有参数)。
      • 方法可以是 publicprotectedprivate(如果是 private,Spring会通过反射调用)。
      • 方法返回值类型必须是 void
      package com.example;
      
      public class MyBean {
          public void destroy() {
              System.out.println("MyBean destroyed!");
          }
      }
      
      <bean id="myBean" class="com.example.MyBean" init-method="init" destroy-method="destroy" />
      

依赖注入

Spring支持两种依赖注入方式:

Setter注入

  • Setter注入是通过调用类的Setter方法来注入依赖项的一种方式。Spring容器会在创建Bean实例后,调用相应的Setter方法来注入依赖项。

  • 必须要有对应的Setter方法

  • Setter注入只考虑一个参数的Setter方法就行,如果Setter方法有多个参数,通常意味着这些参数是紧密相关的,可以考虑使用构造器注入

  • 通过<property>标签注入依赖。

<bean id="myService" class="com.example.MyServiceImpl">
    <property name="myRepository" ref="myRepository" />
</bean>
  1. 注入基本类型

    中的name值为set方法去掉set并小写第一个字母

    <bean id="userService" class="com.example.UserService">
        <property name="maxUsers" value="100" />
    </bean>
    
    public class UserService {
        private int maxUsers;
    
        public void setMaxUsers(int maxUsers) {
            this.maxUsers = maxUsers;
        }
    }
    
  2. 注入集合类型

    • Spring支持注入集合类型,如ListSetMap

    • List

      <bean id="userService" class="com.example.UserService">
          <property name="userNames">
              <list>
                  <value>Alice</value>
                  <value>Bob</value>
                  <value>Charlie</value>
              </list>
          </property>
      </bean>
      
    • map

      <bean id="userService" class="com.example.UserService">
          <property name="userAges">
              <map>
                  <entry key="Alice" value="25" />
                  <entry key="Bob" value="30" />
                  <entry key="Charlie" value="35" />
              </map>
          </property>
      </bean>
      
    • set

      <bean id="userService" class="com.example.UserService">
          <property name="userRoles">
              <set>
                  <value>ADMIN</value>
                  <value>USER</value>
                  <value>GUEST</value>
              </set>
          </property>
      </bean>
      
  3. 注入自定义对象

    • 使用<ref>标签引用其他Bean

    • <bean id="myService" class="com.example.MyServiceImpl">
          <property name="myRepository" ref="myRepository" />
      </bean>
      
  4. 注入集合中为自定义对象

    • List

      • <bean id="userService" class="com.example.UserService">
            <property name="users">
                <list>
                    <ref bean="user1" />
                    <ref bean="user2" />
                    <ref bean="user3" />
                </list>
            </property>
        </bean>
        
    • set

      • <bean id="userService" class="com.example.UserService">
            <property name="users">
                <set>
                    <ref bean="user1" />
                    <ref bean="user2" />
                    <ref bean="user3" />
                </set>
            </property>
        </bean>
        
    • map

      • <bean id="userService" class="com.example.UserService">
            <property name="userMap">
                <map>
                    <entry key="user1" value-ref="user1" />
                    <entry key="user2" value-ref="user2" />
                    <entry key="user3" value-ref="user3" />
                </map>
            </property>
        </bean>
        

构造函数注入

通过<constructor-arg>标签注入依赖。

<bean id="myService" class="com.example.MyServiceImpl">
    <constructor-arg ref="myRepository" />
</bean>
  • <constructor-arg>:定义构造函数参数:
    • ref:引用其他Bean(用于注入其他Bean)。
    • value:注入基本类型或字符串值。
    • index:指定参数的位置(从0开始)。
    • type:指定参数的类型(用于消除歧义)。
  1. 注入基本类型或字符串

    • 使用value属性注入基本类型或字符串值
    <bean id="myService" class="com.example.MyService">
        <constructor-arg value="42"/>
        <constructor-arg value="Hello, World!"/>
    </bean>
    
    public MyService(int number, String message) {
        this.number = number;
        this.message = message;
    }
    
  2. 使用ref:引用其他Bean

  3. 按照顺序注入

    • 如果构造函数有多个参数,Spring会按照<constructor-arg>的顺序匹配参数

    • <bean id="myService" class="com.example.MyService">
          <constructor-arg ref="myRepository"/>
          <constructor-arg value="Hello, World!"/>
      </bean>
      
    • public MyService(MyRepository repository, String message) {
          this.repository = repository;
          this.message = message;
      }
      
  4. 按照参数名称

    • 可以通过 name 属性指定参数名称,避免顺序问题。

    • <bean id="userService" class="com.example.UserService">
          <constructor-arg name="message" value="Hello, World!"/>
          <constructor-arg name="repository" ref="myRepository"/>
      </bean>
      
  5. 按索引注入

    • 如果参数顺序不明确,可以使用index属性指定参数的位置

    • <bean id="myService" class="com.example.MyService">
          <constructor-arg index="1" value="Hello, World!"/>
          <constructor-arg index="0" ref="myRepository"/>
      </bean>
      
  6. 按类型注入

    • 如果参数类型不明确,可以使用type属性指定参数的类型

    • <bean id="myService" class="com.example.MyService">
          <constructor-arg type="com.example.MyRepository" ref="myRepository"/>
          <constructor-arg type="java.lang.String" value="Hello, World!"/>
      </bean>
      
  7. 注入集合

    • List

      • <bean id="myService" class="com.example.MyService">
            <constructor-arg>
                <list>
                    <value>Item 1</value>
                    <value>Item 2</value>
                    <value>Item 3</value>
                </list>
            </constructor-arg>
        </bean>
        
    • set

      • <bean id="myService" class="com.example.MyService">
            <constructor-arg>
                <set>
                    <value>Item 1</value>
                    <value>Item 2</value>
                    <value>Item 3</value>
                </set>
            </constructor-arg>
        </bean>
        
    • map

      • <bean id="myService" class="com.example.MyService">
            <constructor-arg>
                <map>
                    <entry key="Key1" value="10"/>
                    <entry key="Key2" value="20"/>
                    <entry key="Key3" value="30"/>
                </map>
            </constructor-arg>
        </bean>
        
    • 注入Properties类型

      • <bean id="myService" class="com.example.MyService">
            <constructor-arg>
                <props>
                    <prop key="username">admin</prop>
                    <prop key="password">123456</prop>
                </props>
            </constructor-arg>
        </bean>
        

注入特殊值

  • 注入空值(null)

    • 在 XML 中,使用 <null/> 标签表示空值

      <bean id="userService" class="com.example.UserService">
          <property name="username">
              <null/>
          </property>
      </bean>
      
    • 在注解中,直接赋值为 null 即可

      @Service
      public class UserService {
          private String username = null; // 直接赋值为 null
      
          // 其他逻辑
      }
      
  • 给数组注入值

    • XML

      <bean id="user" class="pojo.User">
          <property name="array">
              <array>
                  <value>1</value>
                  <value>2</value>
              </array>
          </property>
      </bean>
      
  • 注入对象

    • 内部Bean

    • 内部 Bean 注入是指在一个 Bean 的定义中嵌套定义另一个 Bean。内部 Bean 的作用域仅限于外部 Bean,不能被其他 Bean 引用

      • <bean id="userService" class="com.example.UserService">
            <property name="userRepository">
                <!-- 定义内部 Bean -->
                <bean class="com.example.UserRepository"/>
            </property>
        </bean>
        
      • 内部 Bean 没有 id 属性-只被该外部Bean使用。

      • 内部 Bean 的作用域仅限于 userService

  • 可以引用外部对象后在使用级联赋值修改对象属性值

    <bean id="address" class="pojo.Address"/>
    
    <bean id="user" class="pojo.User">
        <property name="username" value="1"/>
        <property name="age" value="20"/>
        <property name="address" ref="address" />
        <property name="address.id" value="11"/>
        <property name="address.name" value="12"/>
    </bean>
    
posted @ 2025-03-18 14:37  QAQ001  阅读(126)  评论(0)    收藏  举报