Spring IoC — 基于XML

本文详细介绍了Spring IoC容器的部署、配置实体类、依赖注入方式,包括set方法、构造器注入,以及bean的作用域和生命周期。还涵盖了自动装配和工作原理,适合初学者理解Spring框架的控制反转与依赖注入机制。
摘要由CSDN通过智能技术生成

一、Spring IoC

Spring IoC 容器组件,可以完成对象的创建、对象属性赋值、对象管理

1.1 Spring框架部署(IoC)

1.1.1 创建Maven工程

  • Java
  • Web

1.1.2 添加SpringIoC依赖

  • core
  • beans
  • aop
  • expression
  • context

在Maven中由于context依赖于其他包,所以导入context后,其他依赖会自动导入

    <!--
        导入jar包就是添加项目依赖 dependencies
    -->
    <dependencies>
        <!--
            写入添加的jar包
        -->
        <!--
            spring 的core包
        https://mvnrepository.com/artifact/org.springframework/spring-core
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency> -->

        <!--
            spring 的bean的包
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>-->

        <!--
            spring 的context的包(只需要这一个包就可以了)
         -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.16.RELEASE</version>
        </dependency>
        
    </dependencies>

1.1.3 创建Spring配置文件

通过配置文件"告诉"Spring容器创建什么对象,给对象属性赋什么值
在resources目录下创建名为 appicationContext.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">
<!-- 对于一个xml文件如果作为框架的配置文件,需要遵守框架的配置规则 -->
<!-- 通常一个框架为了让开发者能够正确的配置,都会提供xml的规范文件(dtd\xsd) -->
</beans>

1.2 SpringIoC使用

使用 SpringIoC组件创建并管理对象

1.2.1 创建一个实体类

public class Student {
     int sId;
     String sName;
     String sex;
     int age;
     String major;
     Date birthday;
}

1.2.2 在Spring配置文件中配置实体类

<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<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">

    <!--
        bean:spring容器创建一个对象
            1. id 创建对象的名字 一般是类名的首字母小写
            2. class 创建什么类型对象  类名+对象名
    -->
    <!--suppress SpringFacetInspection -->
    <bean id="student" class="com.sxy.entity.Student">
            <!--
                通过property标签给属性赋值
            -->
        <property name="sId" value="1002"/>
        <property name="sName" value="李四"/>
        <property name="major" value="计算机"/>
        <property name="sex" value=""/>
        <property name="age" value="18"/>
        <!--
            birthday是什么类型?
              Date birthday; 是java.util.Data 对象类型
              ref:references的缩写,是引用的意思。 引用容器里面的一个对象;
              方式1:
                <property name="birthday" ref="date"></property>
                <bean id="date" class="java.util.Date"></bean>
              方式2:
                  <property name="birthday">
                        <bean class="java.util.Date"></bean>
                  </property>
        -->
        <property name="birthday">
            <bean class="java.util.Date"></bean>
        </property>
    </bean>

    <!--
        让spring帮我们创建一个date对象

    <bean id="date" class="java.util.Date"></bean> -->

</beans>

1.2.3 初始化Spring对象工厂,获取对象

ClassPathXMLApplicationContext

        // 加载配置文件 得到spring的上下文对象
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取对象,通过getBean("bean标签里面的id属性值")方法
        Student student = (Student) context.getBean("student");//返回的是object对象
        System.out.println(student);

1.3 IoC和DI

  • IoC (Inverse of Control) 控制反转,通过Spring对象工厂完成对象的创建
  • DI (Dependency Injection)依赖注入,在Spring完成对象创建的同时依赖Spring容器完成对象属性的赋值

1.3.1 IoC

当我们需要通过Spring对象工厂创建某个类的对象时候,需要将这个交给Spring管理——通过
bean标签配置

<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.sxy.entity.Student"></bean>

1.3.2 DI

通过Spring容器给创建的对象属性赋值

<bean id="clazz" class="com.sxy.entity.Clazz"></bean>
<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.sxy.entity.Student" autowire="byName">
<property name="stuNum" value="10001"/>
</bean>

1.4 DI依赖注入

1.4.1 依赖注入三种方式

Spring容器加载配置文件之后,通过反射创建类的对象,并给属性赋值;
Spring容器通过反射实现属性注入有三种方式:

  • set方法注入
  • 构造器注入
  • 接口注入(不常用)

1.4.2 set方法注入

在bean标签中通过配置property标签给属性属性赋值,实际上就是通过反射调用set方法完成属性的注入

简单类型及字符串

直接通过property标签的value属性赋值

<!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示-->
<bean id="stu" class="com.cg.ioc.bean.Student" autowire="byName">
<!-- 简单类型 -->
<property name="stuNum" value="10001"/>
<property name="stuAge" value="12"/>
<!-- 字符串类型-->
<property name="sName" value="abcd"/>
</bean>
日期类型

方式1:在property标签中通过ref引用Spring容器中的一个对象

<!--创建一个java.util.Date的bean,再通过ref引入-->
<bean id="date" class="java.util.Date"></bean>

<bean id="stu" class="com.cg.ioc.bean.Student" >
<!-- 日期类型-->
<property name="enterenceTime" ref="date"/>
</bean>

方式2:在property标签中添加子标签bean来指定对象

<bean id="stu" class="com.cg.ioc.bean.Student" >
<!-- 日期类型-->
<!--直接在property中创建一个java.util.Date的bean-->
<property name="enterenceTime">
<bean class="java.util.Date"/>
</property>

</bean>
自定义类对象属性

方式1:在property标签中通过ref引用Spring容器中的一个对象(与时间类型一致)

<bean id="cla" class="com.cg.ioc.bean.Clazz">
<!--com.cg.ioc.bean.Clazz对象中的数据-->
<property name="classId" value="2010"/>
<property name="className" value="Java2010"/>
</bean>

<bean id="stu" class="com.cg.ioc.bean.Student">
<!-- 自定义对象类型-->
<property name="clazz" ref="cla"/>
</bean>

方式2:在property标签中添加子标签bean来指定对象(与时间类型一致)

<bean id="stu" class="com.cg.ioc.bean.Student">
<!-- 自定义对象类型-->
<property name="clazz">
<bean class="com.cg.ioc.bean.Clazz">
<!--com.cg.ioc.bean.Clazz对象中的数据-->
<property name="classId" value="2010"/>
<property name="className" value="Java2010"/>

</bean>
</property>
</bean>
集合类型
  • List

    • List List中的元素是字符串或者简单类型的封装类
      方法一:写在一个value中用逗号隔开
      <property name="hobbies" value="旅游,电影"/>
      
      方式二:用list标签列举
      <property name="hobbies" >
      <list>
      <value>旅游</value>
      <value>电影</value>
      <value>Java</value>
      </list>
      </property>
      
    • List List中的元素是对象类型
      方式1:通过ref引用Spring容器中的一个对象
      <property name="hobbies" >
      <list>
      <ref bean="book"></ref> <!--引用容器中的备案-->
      <ref bean="book"></ref>
      </list>
      </property>
      
      方式2:在property标签中添加子标签bean来指定对象
      <property name="hobbies" >
      <list>
      <bean class="com.cg.ioc.bean.Book"/>
      <bean class="com.cg.ioc.bean.Book"/>
      <bean class="com.cg.ioc.bean.Book"/>
      <bean class="com.cg.ioc.bean.Book"/>
      </list>
      </property>
      
  • Set
    set和list元素注入方式相同

    <property name="sets">
    <set>
    <!--和list元素注入方式相同-->
    </set>
    </property>
    
  • Map

    <property name="maps">
      <map>
       <!--map是由一组key和value组成的entry-->
        <entry>
          <key>
          <!--key的值-->
            <value>k1</value>
          </key>
          <!--value的值-->
          <value>123</value>
        </entry>
        
        <entry>
          <key>
            <value>k2</value>
          </key>
          <value>456</value>
        </entry>
        
      </map>
    </property>
    
  • Properties

    <property name="properties">
    <props>
    <prop key="k1">aaa</prop>
    <prop key="k2">bbb</prop>
    </props>
    </property>
    

1.4.3 构造器注入

bean对象

public class Student {
    private String stuNum;
    private String stuName;
    private String stuGender;
    private int stuAge;
    private double weight;
    private Date enterenceTime; //入学日期
//集合类型属性
    private Clazz clazz;
    public Student(String stuNum, String stuName, String stuGender, int stuAge, double weight, Date enterenceTime, Clazz clazz) {
    this.stuNum = stuNum;
    this.stuName = stuName;
    this.stuGender = stuGender;
    this.stuAge = stuAge;
    this.weight = weight;
    this.enterenceTime = enterenceTime;
    this.clazz = clazz;
}
}
简单类型、字符串、对象
<bean id="date" class="java.util.Date"></bean>
<bean id="stu" class="com.cg.ioc.bean.Student">

    <!--index 对应构造器参数位置的索引,可不写,如不写则按上下顺序对应-->
    <constructor-arg index="0" value="10001"/> <!--字符串类型-->
    <constructor-arg index="2" value=""/>
    <constructor-arg index="1" value="张三"/>
    <constructor-arg index="3" value="21"/> <!--简单类型-->
    <constructor-arg index="4" value="62.5"/>
    <constructor-arg index="5" ref="date"/> <!--对象类型-->
    <constructor-arg index="6"> <!--对象类型-->
    <bean class="com.cg.ioc.bean.Clazz"></bean>
    </constructor-arg>
</bean>
集合类型属性
<bean id="stu1" class="com.cg.ioc.bean.Student">
        <!--list类型-->
    <constructor-arg index="0">
        <list>
            <value>11</value>
            <value>22</value>
            <value>33</value>
        </list>
    </constructor-arg>
            <!--set类型-->
    <constructor-arg index="1">
        <set>
            <value>aa</value>
            <value>bb</value>
            <value>cc</value>
        </set>
    </constructor-arg>
            <!--map类型-->
    <constructor-arg index="2">
        <map>
            <entry>
                <key><value>key1</value></key>
                <value>value1</value>
            </entry>
            <entry>
                <key><value>key2</value></key>
                <value>value2</value>
            </entry>
        </map>
    </constructor-arg>
            <!--Properties类型-->
    <constructor-arg index="3">
        <props>
            <prop key="k1">v1</prop>
            <prop key="k2">v2</prop>
        </props>
    </constructor-arg>
</bean>

1.5 Bean的作用域

在bean标签可以通过scope属性指定对象的的作用域

  • scope=“singleton” 表示当前bean是单例模式(默认饿汉模式,Spring容器初始化阶段就会
    完成此对象的创建;当在bean标签中设置 lazy-init="true"变为懒汉模式)

    <!--多个getBean获取的是同一对象-->
    <bean id="book" class="com.cg.ioc.bean.Book" scope="singleton" lazy-init="true">
    </bean>
    
  • scope=“prototype” 表示当前bean为非单例模式,每次通过Spring容器获取此bean的对象时
    都会创建一个新的对象

    <!--每次getBean获取的都是新的对象-->
    <bean id="book" class="com.cg.ioc.bean.Book" scope="prototype"></bean>
    

1.6 Bean的生命周期

简化版本 :

在这里插入图片描述

在bean标签中通过init-method属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行,通过destroy-method属性指定当前bean的销毁方法,销毁方法在对象销毁之前执行–>
Bean类

public class Book {
private int bookId;
private String bookName;

//初始化方法:在创建当前类对象时调用的方法,进行一些资源准备工作
public void init(){
System.out.println("-------init");
}
//销毁方法:在Spring容器销毁对象时调用此方法,进行一些资源回收性的操作
public void destory(){
System.out.println("-------destory");
}
}

Spring配置文件

<bean id="book" class="com.cg.ioc.bean.Book" scope="prototype"initmethod="init"
destroy-method="destory" ></bean>

相对完整 :

在这里插入图片描述

  • 实例化:Spring对Bean进行实例化(默认调用无参构造器),scope为 singleton
  • 属性赋值:容器对属性进行注入
  • 如果Bean实现了 BeanNameAware 接口,容器就将Bean的Id通过 setBeanName 方法传进来
  • 如果Bean实现了 BeanFactory 接口,容器就将BeanFactory容器实例通过 setBeanFactory 传入
  • 如果Bean实现了 ApplicationContextAware 接口,那么容器将Bean所在的 应用上下文 引用传入
  • 如果Bean实现了 BeanPostProcessor 接口,那么就调用 postProcessBeforeInitialization方法对Bean进行前置处理
  • 如果Bean实现了 InitializingBean 接口,那就通过调用 afterPropertiesSet 方法进行 自定义的初始化 ,作用等同于,为Bean设置 init-method 属性
  • 如果Bean实现了 BeanPostProcessor 接口,那么就调用 postProcessAfterInitialization 方法对Bean进行后置处理
  • 如果Bean实现了 DisposableBean 接口,那就通过调用 destroy 方法进行 自定义的销毁 等同于为
    Bean设置 destroy-method 属性
<bean id="fierceMan" class="com.softeem.entity.FierceMan"
scope="singleton" init-method="customInit" destroy-method="customDestroy">
<!-- 背心,短裤,人字拖 -->
<property name="clothes">
<set>
<value>背心</value>
<value>短裤</value>
<value>人字拖</value>
</set>
</property>
</bean>
public class FierceMan implements BeanFactoryAware, InitializingBean, DisposableBean {
private BeanFactory factory;
/**
* 猛男喜欢穿的衣服
*/
private Set<String> clothes;
/**
* 猛男喜欢的电脑
*/
private List<Computer> computerList;
/**
* 猛男喜欢看的卡通
*/
private Map<String,Object> cartoonMap;
/**
* 猛男存小姐姐的数据库信息
*/
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public Map<String, Object> getCartoonMap() {
return cartoonMap;
}
public void setCartoonMap(Map<String, Object> cartoonMap) {
this.cartoonMap = cartoonMap;
}
public List<Computer> getComputerList() {
return computerList;
}
public void setComputerList(List<Computer> computerList) {
this.computerList = computerList;
}
public Set<String> getClothes() {
return clothes;
}
public void setClothes(Set<String> clothes) {
System.out.println("通过set方法注入clothes");
this.clothes = clothes;
}
public FierceMan() {
System.out.println("猛男被无参构造了");
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
factory = beanFactory;
}
@Override
public void destroy() throws Exception {
System.out.println("实现了DisposableBean的自定义销毁的方法");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("实现了InitializingBean的初始化方法");
}
public void customInit(){
System.out.println("init-method定义的方法");
}
public void customDestroy(){
System.out.println("destroy-method定义的方法");
}

1.7 自动装配

自动装配:Spring在实例化当前bean的时候从Spring容器中找到匹配的实例赋值给当前bean的属

自动装配策略有两种:

  • byName 根据当前Bean的属性名在Spring容器中寻找匹配的对象 ,如果根据name找打了
    bean但是类型不匹配则抛出异常

    <bean id="clazz" class="com.cg.ioc.bean.Clazz"></bean>
    <!--com.cg.ioc.bean.Student中包含com.cg.ioc.bean.Clazz对象,自动装配时根据name:Clazz寻找匹配的对象-->
    <bean id="stu2" class="com.cg.ioc.bean.Student" autowire="byName"></bean>
    
  • byType 根据当前Bean的属性类型在Spring容器中寻找匹配的对象,如果根据类型找到了多
    个bean也会抛出异常

    <bean id="clazz2" class="com.cg.ioc.bean.Clazz"></bean>
      <!--com.cg.ioc.bean.Student中包含com.cg.ioc.bean.Clazz对象,自动装配时根据class:Clazz寻找匹配的对象-->
    <bean id="stu2" class="com.cg.ioc.bean.Student" autowire="byType"></bean>
    

1.8 SpringIoC 工作原理

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值