Spring--IOC基于XML管理bean

news2024/12/22 17:21:56

IOC容器

IOC思想

IOC:Inversion of Control 即反转控制

  1. 获取资源的传统方式
    自己做饭:买菜、洗菜、择菜、改刀、炒菜,全过程参与,费时费力,必须清楚了解资源创建整个过程中的全部细节且熟练掌握。
    在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效率。

  2. 反转控制方式获取资源
    点外卖:下单、等、吃,省时省力,不必关心资源创建过程的所有细节。
    反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向--------改由容器主动的将资源推送给需要的组件,开发人员不需要知道容路是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效率。这种行为也称为查找的被动开式。

  3. DI
    Dl: Dependency Injection,翻译过来是依赖注入。
    DI是IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如:setter 方法)接受来自于容器的资源注入。相对于IOC而言,这种表述更直接。

所以结论是:IOC就是一种反转控制的思想,而DI是对IOC的一种具体实现

IOC容器在Spring中的实现

Spring的IOC容器就是IOC思想的一个落地的产品的实现。IOC容器中管理的组件也叫bean,在创建bean之前,首先需要创建IOC容器。Spring提供了IOC容器的两种实现方式

BeanFactory

这是IOC容器的基本实现,是Spring内部使用的接口,面向Spring本身,不提供给开发人员使用

ApplicationContext

BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory

ApplicationContext的主要实现类

在这里插入图片描述

类型名简介
ClassPathXmlApplicationContext通过读取类路径下的XML格式的配置文件创建IOC容器对象
FileSystemXmlApplicationContext通过文件系统路径读取XML格式的配置文件创建IOC容器对象
ConfigurableApplicationContextApplicationContext的子接口,包含一些拓展方法refresh()和close(),让ApplicationContext具有启动、关闭和刷新上下文的能力
WebApplicationContext专门为web应用准备,基于web环境创建IOC容器对象,并将对象引入存入ServletContext域中

基于XML管理bean

实验一:入门案例

  1. 创建Maven Module
  2. 引入依赖
    pom.xml
    <dependencies>
<!--        基于Maven依赖传递性,导入spring-context依赖即可导入当前所需的索引jar包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.1</version>
        </dependency>
<!--        junit测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
  1. 创建HelloWorld
package com.bijing.spring.pojo;

/**
 * @author 毕晶
 * @date 2022/11/11 14:50
 */
public class HelloWorld {
    public void sayHello(){
        System.out.println("hello,spring");
    }
}

  1. 创建Spring的配置文件
    在这里插入图片描述

  2. 在Spring的配置文件中配置bean
    application.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">
<!--
    bean:配置一个bean对象,将对象交给IOC容器管理
    属性:
        id:bean的唯一标识,不能重复
        class:设置bean对象所对应的类型
-->
    <bean id="helloworld" class="com.bijing.spring.pojo.HelloWorld"></bean>
</beans>
  1. 创建测试类测试
package com.bijing.spring.test;

import com.bijing.spring.pojo.HelloWorld;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 毕晶
 * @date 2022/11/11 14:56
 */
public class HelloWorldTest {
    @Test
    public void testHelloWorld(){
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("application.xml");
        //获取IOC容器中的bean
        HelloWorld helloworld = (HelloWorld) ioc.getBean("helloworld");
        helloworld.sayHello();
    }
}

实验二:获取bean

  1. 方式一:根据id获取
  2. 方式二:根据类型获取
  3. 方式三:根据id和类型
  4. 注意:注意:根据类型获取bean时,要求IOC中有且只有一个类型匹配的bean;若没有一个类型匹配的bean,也会抛出异常
  5. 拓展

如果组件类实现了接口,根据接口类型可以获取bean吗
可以,前提是bean唯一

        //此时Student实现了Person接口,组件类是Student,所以编译类型是Person,运行类型是Student
        Person person = ioc.getBean(Person.class);
        System.out.println(person.getClass());//class com.bijing.spring.pojo.Student

如果一个接口有多个实现类,这些实现类都配置了bean,根据接口类型可以获取bean吗
不行,因为bean不唯一
此时,因为Person的实现类有多个,不知道用哪个实现类的bean
7. 结论
根据类型来获取bean时,在满足bean唯一的前提下,其实只是看:对象instanceof指定的类型 的返回结果,只要是true就可以认为和类型匹配,就能够获取到。即通过bean的类型,bean所继承的类的类型,bean所实现的接口类型都可以获取bean

实验三:依赖注入之setter注入

  1. 创建学生类Student
  2. 配置bean时为属性赋值
    <bean id="studentTwo" class="com.bijing.spring.pojo.Student">
        <!--
            property:通过成员变量的set方法进行赋值
            name:设置需要赋值的属性名(和set方法有关)
            value:设置为属性所赋的值
           -->
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
        <property name="age" value="23"></property>
        <property name="gender" value=""></property>
    </bean>
  1. 测试
    @Test
    public void testDI() {
        //获取IOC容器
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        Student studentTwo = ioc.getBean("studentTwo", Student.class);
        System.out.println(studentTwo);
    }

实验四:依赖注入之构造器注入

  1. 在Student类中添加有参构造器
  2. 配置bean
    <!--
        constructor-arg:通过构造器进行赋值,顺序和构造器中的参数顺序一样
        value:设置为属性所赋的值
        name:可以指定赋值的属性
    -->
    <bean id="studentThree" class="com.bijing.spring.pojo.Student">
        <constructor-arg value="1002"></constructor-arg>
        <constructor-arg value="李四"></constructor-arg>
        <constructor-arg value="24" name="age"></constructor-arg>
        <constructor-arg value=""></constructor-arg>
    </bean>
  1. 测试
        Student studentThree = ioc.getBean("studentThree", Student.class);
        System.out.println(studentThree);

实验五:特殊值处理

  1. 字面量赋值
什么是字面量?
int a=10;
声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a的时候,我们实际拿到的值是10
如果a是带引号的:'a',那么它现在不是一个变量,它就是代表a这个字母,这就是字面量。
  1. null值
    <!--    使用null标签给属性赋值null,另外属性赋值也可以不用value属性用value标签-->
    <bean id="studentFour" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1003"></property>
        <property name="sname" value="王五"></property>
        <property name="gender">
            <null></null>
        </property>
    </bean>
  1. xml实体
    <!--
        xml实体如sname="<王五>"
            <: &lt;
            >: &gt;
    -->
    <bean id="studentFour" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1003"></property>
        <property name="sname" value="&lt;王五&gt;"></property>
        <property name="gender">
            <null></null>
        </property>
    </bean>
  1. CDATA节
    <!--    CDATA区:里面内容原样输出,快捷键大写CD,是xml中的一个标签,不能写在属性中-->
    <bean id="studentFour" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1003"></property>
        <!--        <property name="sname" value="&lt;王五&gt;"></property>-->
        <property name="sname">
            <value><![CDATA[<王五>]]></value>
        </property>
        <property name="gender">
            <null></null>
        </property>
    </bean>

实验六:为类类型属性赋值

  1. 创建班级类Clazz
package com.bijing.spring.pojo;

/**
 * @author 毕晶
 * @date 2022/11/11 19:27
 */
public class Clazz {
    private Integer cid;
    private String cname;

    public Clazz(Integer cid, String cname) {
        this.cid = cid;
        this.cname = cname;
    }

    public Clazz() {
    }

    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    @Override
    public String toString() {
        return "Clazz{" +
                "cid=" + cid +
                ", cname='" + cname + '\'' +
                '}';
    }
}

  1. 修改Student类
package com.bijing.spring.pojo;

/**
 * @author 毕晶
 * @date 2022/11/11 15:09
 */
public class Student implements Person {
    private Integer sid;
    private String sname;
    private Integer age;
    private String gender;
    private Clazz clazz;

    public Student() {
    }

    public Student(Integer sid, String sname, Integer age, String gender) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
        this.gender = gender;
    }

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", clazz=" + clazz +
                '}';
    }
}

  1. 方式一:引用外部已声明的bean
    <!--    ref:引用IOC容器中的某个bean的id-->
    <bean id="studentFive" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="sname" value="赵六"></property>
        <property name="age" value="26"></property>
        <property name="gender" value=""></property>
        <property name="clazz" ref="clazzOne"></property>
    </bean>
    <bean id="clazzOne" class="com.bijing.spring.pojo.Clazz">
        <property name="cid" value="1111"></property>
        <property name="cname" value="三年一班"></property>
    </bean>
  1. 方式二:内部bean

    <!--  使用内部bean,内部bean对象不能通过IOC容器获取,就和内部类不能在外部访问一样-->
    <bean id="studentFive" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="sname" value="赵六"></property>
        <property name="age" value="26"></property>
        <property name="gender" value=""></property>
        <property name="clazz">
            <bean id="clazzInner" class="com.bijing.spring.pojo.Clazz">
                <property name="cid" value="1111"></property>
                <property name="cname" value="三年一班"></property>
            </bean>
        </property>
    </bean>
  1. 方式三:级联属性赋值
    <bean id="studentFive" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="sname" value="赵六"></property>
        <property name="age" value="26"></property>
        <property name="gender" value=""></property>
        <!--        使用级联的方式,要提前为clazz赋值或者实例化-->
        <property name="clazz" ref="clazzOne"></property>
        <property name="clazz.cid" value="1111"></property>
        <property name="clazz.cname" value="三年一班"></property>
    </bean>
    <bean id="clazzOne" class="com.bijing.spring.pojo.Clazz">
        <property name="cid" value="1111"></property>
        <property name="cname" value="三年一班"></property>
    </bean>

实验七:为数组类型属性赋值

  1. 修改Student类
package com.bijing.spring.pojo;

import java.util.Arrays;

/**
 * @author 毕晶
 * @date 2022/11/11 15:09
 */
public class Student implements Person {
    private Integer sid;
    private String sname;
    private Integer age;
    private String gender;
    private String[] hobby;
    private Clazz clazz;


    public Student() {
    }

    public Student(Integer sid, String sname, Integer age, String gender) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
        this.gender = gender;
    }

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                ", clazz=" + clazz +
                '}';
    }
}

  1. 配置bean
        <!--  字面量类型使用value来为数组中的每个变量赋值,如果是引用类型使用ref标签 <ref bean="hobby1"></ref>-->
        <property name="hobby">
            <array>
                <value>抽烟</value>
                <value>喝酒</value>
                <value>烫头</value>
                <value>蹦迪</value>
            </array>
        </property>

实验八:为集合类型属性赋值

  1. 为List集合类型的属性赋值
    通过list标签
<bean id="clazzOne" class="com.bijing.spring.pojo.Clazz">
        <property name="cid" value="1111"></property>
        <property name="cname" value="三年一班"></property>
        <property name="students">
            <list>
                <ref bean="studentOne"></ref>
                <ref bean="studentTwo"></ref>
                <ref bean="studentThree"></ref>
                <ref bean="studentFour"></ref>
                <ref bean="studentFive"></ref>
                <!--                也可以直接新建Student-->
                <bean id="newStudent1" class="com.bijing.spring.pojo.Student">
                    <property name="sid" value="1009"></property>
                    <property name="sname" value="新同学"></property>
                    <property name="age" value="26"></property>
                    <property name="gender" value=""></property>
                    <property name="clazz">
                        <bean id="clazzInner" class="com.bijing.spring.pojo.Clazz">
                            <property name="cid" value="1111"></property>
                            <property name="cname" value="三年一班"></property>
                        </bean>
                    </property>
                </bean>
            </list>
        </property>
    </bean>

通过util:list
需要导入util约束

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"

    <bean id="clazzOne" class="com.bijing.spring.pojo.Clazz">
        <property name="cid" value="1111"></property>
        <property name="cname" value="三年一班"></property>
        <property name="students" ref="students">
        </property>
    </bean>
    <!--    配置一个集合类型的bean,需要使用一个util的约束-->
    <util:list id="students">
        <ref bean="studentOne"></ref>
        <ref bean="studentTwo"></ref>
    </util:list>
  1. 为Map集合类型的属性赋值
//Student增加下面属性
    private Map<String, Teacher> teacherMap;
 <bean id="studentFive" class="com.bijing.spring.pojo.Student">
        <property name="sid" value="1004"></property>
        <property name="sname" value="赵六"></property>
        <property name="age" value="26"></property>
        <property name="gender" value=""></property>
        <property name="clazz">
            <bean id="clazzInner" class="com.bijing.spring.pojo.Clazz">
                <property name="cid" value="1111"></property>
                <property name="cname" value="三年一班"></property>
            </bean>
        </property>
        <!--  字面量类型使用value来为数组中的每个变量赋值,如果是引用类型使用ref标签 <ref bean="hobby1"></ref>-->
        <property name="hobby">
            <array>
                <value>抽烟</value>
                <value>喝酒</value>
                <value>烫头</value>
                <value>蹦迪</value>
            </array>
        </property>
        <!--
            Map赋值:
            第一种: map标签,一个entry表示一个键值对
            第二种:util: map
        -->
        <!--        <property name="teacherMap">-->
        <!--            <map>-->
        <!--                <entry key="10086" value-ref="teacherOne"></entry>-->
        <!--                <entry key="10087" value-ref="teacherTwo"></entry>-->
        <!--            </map>-->
        <!--        </property>-->
        <property name="teacherMap" ref="teachers"></property>
    </bean>
    
    <bean id="teacherOne" class="com.bijing.spring.pojo.Teacher">
        <property name="tid" value="10086"></property>
        <property name="tname" value="大宝"></property>
    </bean>
    <bean id="teacherTwo" class="com.bijing.spring.pojo.Teacher">
        <property name="tid" value="10087"></property>
        <property name="tname" value="小宝"></property>
    </bean>

    <util:map id="teachers">
        <entry key="10086" value-ref="teacherOne"></entry>
        <entry key="10087" value-ref="teacherTwo"></entry>
    </util:map>
  1. 引用集合类型的bean
    引入util约束,使用util: list、util: map标签,具体使用见上面

实验九:p命名空间

引入约束p,应该是指property

       xmlns:p="http://www.springframework.org/schema/p"
<!--    p命名空间,要引入约束p-->
    <bean id="studentSix" class="com.bijing.spring.pojo.Student"
          p:sid="1005" p:sname="小明" p:teacherMap-ref="teachers"></bean>

实验十:引入外部属性文件

jdbc为例

  1. 加入依赖
    pom.xml
      <!--        mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <!--        数据源-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.31</version>
        </dependency>
  1. 创建外部属性文件
    jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimeZone=UTC"
jdbc.username=root
jdbc.password=root1234
  1. 引入属性文件
    引入约束context
       xmlns:context="http://www.springframework.org/schema/context"
    <!--    引入jdbc.properties,之后可以通过${key}的方式访问value-->
    <context:property-placeholder location="jdbc.properties"/>
  1. 配置bean
    <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>
  1. 测试
public class DataSourceTest {
    @Test
    public void testDataSource() throws SQLException {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-datasource.xml");
        DruidDataSource datasource = ioc.getBean("datasource", DruidDataSource.class);
        DruidPooledConnection connection = datasource.getConnection();
        System.out.println(connection);
    }
}

实验十一:bean的作用域

  1. 概念
    在Spring中可以通过配置bean标签的scope来指定bean的作用域范围,各取值含义参如下表
取值含义创建对象的时机
singleton(默认)在IOC容器中,这个bean对象始终为单例IOC容器初始化
prototype这个bean在IOC容器中有多个实例获取bean时

如果在WebApplicationContext环境下还有另外两个作用域(但不常用)

取值含义
request在一个请求范围内有效
session在一次会话范围内有效
  1. 创建类Student
    就是之前使用的Student类
  2. 配置bean
  <!--
        scope:设置bean的作用域
        scope="singleton|prototype"
            singleton:表示获取该bean所对应的对象都是同一个对象(单例,用的比较多)
            prototype:表示获取该bean所对应的对象不是同一个对象(多例)
    -->
    <bean id="student" class="com.bijing.spring.pojo.Student" scope="prototype">
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
    </bean>
  1. 测试
    @Test
    public void testScope() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-scope.xml");
        Student student1 = ioc.getBean("student", Student.class);
        Student student2 = ioc.getBean("student", Student.class);
        System.out.println(student1 == student2);//true说明是单例模式创建的student,是同一个对象
    }

实验十二:bean的生命周期

  1. 具体的生命周期过程
  • bean对象创建(调用无参构造器)
  • 给bean对象设置属性
  • bean对象初始化之前操作(由bean的后置处理器负责)
  • bean对象初始化(需在配置bean时指定初始化方法)
  • bean对象初始化之后操作(由bean的后置处理器负责)
  • bean对象就绪可以使用
  • bean对象的销毁(需要在配置bean的时候指定销毁方法)
  • IOC容器关闭
  1. 创建类User
package com.bijing.spring.pojo;

/**
 * @author 毕晶
 * @date 2022/11/11 22:31
 */
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;

    public User() {
        System.out.println("生命周期1:实例化");
    }

    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println("生命周期2:依赖注入");
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }


    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

    public void initMethod() {
        System.out.println("生命周期3:初始化");
    }

    public void destroyMethod() {
        System.out.println("生命周期4:销毁");
    }
}

  1. 配置bean
<?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">


    <bean id="user" class="com.bijing.spring.pojo.User" init-method="initMethod" destroy-method="destroyMethod">
        <property name="id" value="1"></property>
        <property name="username" value="admin"></property>
        <property name="password" value="123456"></property>
        <property name="age" value="23"></property>
    </bean>
</beans>
  1. 测试
package com.bijing.spring.test;

import com.bijing.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 毕晶
 * @date 2022/11/11 22:43
 */
public class LifeCycleTest {
    /**
     * 1.实例化
     * 2.依赖注入
     * 3.初始化 要通过bean标签的init-method属性指定方法
     * 4.IOC容器关闭时销毁 要通过bean标签的destroy-method属性指定方法
     *      
     * 注意:
     * 若bean的作用域是单例时,生命周期的前三个步骤会在获取IOC容器时执行
     * 若bean的作用域是多例时,生命周期的前三个步骤会在获取bean时执行,销毁步骤不由ioc控制了
     */
    @Test
    public void testLifeCycle() {
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中拓展了刷新和关闭容器的方法
        //注意:1.如果是bean对象是单例模式获取的,则生命周期前三个步骤已经完成,即ioc容器创建的时候bean对象就已经创建并完成了初始化
        //    2.如果是多例,destroy步骤不由ioc来控制了,即ioc.close()时销毁方法不执行
        ConfigurableApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        //ApplicationContext没有close方法
        ioc.close();
    }
}

  1. bean的后置处理器
    bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某—个bean生效,而是 针对IOC容器中所有bean都会执行

创建bean的后置处理器

package com.bijing.spring.pojo.com.bijing.spring.process;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author 毕晶
 * @date 2022/11/12 10:17
 */
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //此方法在bean的生命周期初始化之前执行
        System.out.println("此方法在bean的生命周期初始化之前执行");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //此方法在bean的生命周期初始化之后执行
        System.out.println("此方法在bean的生命周期初始化之后执行");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

配置bean的后置处理器

    <bean id="myBeanPostProcessor" class="com.bijing.spring.pojo.com.bijing.spring.process.MyBeanPostProcessor"></bean>

实验十三:FactoryBean

  1. 简介
    Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean,这两种Bean都被容器管理,但工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该FactoryBean的getObject方法所返回的对象。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

  2. 创建类UserFactoryBean

package com.bijing.spring.factory;

import com.bijing.spring.pojo.User;
import org.springframework.beans.factory.FactoryBean;

/**
 * @author 毕晶
 * @date 2022/11/12 10:35
 */
public class UserFactoryBean implements FactoryBean<User> {
    @Override
    public User getObject() throws Exception {
        return new User();
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

  1. 配置bean
    <bean class="com.bijing.spring.factory.UserFactoryBean"></bean>
  1. 测试
public class FactoryBeanTest {
    @Test
    public void testFactoryBean() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-factory.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
    }
}

实验十四:基于xml的自动装配

自动装配:
根据指定的策略,在IOC容器中匹配某一个bean,自动为指定的bean中所依赖的类类型或者接口类型属性赋值

  1. 场景模拟
    创建UserController
public class UserController {
    private UserService userService;

    //UserService会变动,不要直接写死,使用set和get方法有利于改动
    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public void saveUser() {
        userService.saveUser();
    }
}
  1. 配置bean
<?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">
    <!--    UserController中有UserService属性,可以根据该属性所对应的类的类型或者接口实现类的类型去IOC容器中匹配,要求类型唯一-->
    <!--    UserController中有UserService属性,可以根据UserService的 将set去掉并且首字母小写的 字符串作为name去IOC容器中匹配id-->
    <bean id="userController" class="com.bijing.spring.controller.UserController" autowire="byType">
        <!--        <property name="userService" ref="userService"></property>-->
    </bean>
    <bean id="userService" class="com.bijing.spring.service.impl.UserServiceIml" autowire="byType">
        <!--        <property name="userDao" ref="userDao"></property>-->
    </bean>
    <bean id="userDao" class="com.bijing.spring.dao.impl.UserDaoImpl"></bean>
</beans>
  1. 测试
package com.bijing.spring.test;

import com.bijing.spring.controller.UserController;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 毕晶
 * @date 2022/11/12 17:13
 */
public class AutowireByXmlTest {

    /**
     * 自动装配:
     * 根据指定的策略,在IOC容器中匹配某个bean,自动为bean中的类类型的属性或者接口类型属性赋值
     * 可以通过bean标签中autowire属性设置自动装配的策略
     * 自动装配策略:
     * #no,default表示不装配,即bean 中的属性不会自动匹配某个bean为属性赋值,此时属性使用默认值
     * #byType:根据要赋值的属性的类型,在IOC容器中匹配某个bean,为属性赋值
     * 注意:1.若通过类型没有找到任何一个类型匹配的bean,此时不匹配,属性使用默认值
     * 2.若通过类型找到了多个类型匹配的bean,此时会抛出异常:
     * 总结:当使用byType实现自动装配时,IOC容器中有且只有一个类型匹配的bean能够为属性赋值
     * #byName:将要赋值的属性的属性名作为bean的id在IOC容器中匹配某个bean为属性赋值
     * 当类型匹配的bean有多个时,此时可以使用byName实现自动装配
     */
    @Test
    public void testAutowireByXml() {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-autowire-xml.xml");
        UserController userController = ioc.getBean(UserController.class);
        userController.saveUser();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5243.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Antd表格性能优化

今天来分享一个实际项目的性能优化的内容。 文章目录一、背景介绍二、性能问题原因及解决方案一、背景介绍 国内React项目大多数人选择配套的UI库的时候都会选择Antd。如果是非常简单的页面用Antd的话其实是完全没问题的&#xff0c;性能感觉不到什么瓶颈&#xff0c;样式也还…

计算机网络

目录 介绍 组成部分 工作方式 功能组成 网络范围分类 传输技术&#xff1a; 总结 标准化工作 RFC文档的作用&#xff1a; 速率&#xff0c;带宽 有容量和速率的区别 带宽 吞吐量 时延&#xff0c;时延带宽积 1.发送时延&#xff1a; 2.传播时延&#xff1a; ​编辑 3.…

Vant组件库 引入 阿里矢量图 添加自己喜欢的 ICON

&#x1f4c3;目录跳转一.矢量图下载&#x1f4a8;使用CDN方式&#x1f389;下载本地&#xff08;推荐&#xff09;二.Vant引入Icon&#x1f5fa;️&#x1f383; 使用方式&#x1f680; 运行效果&#xff1a;一.矢量图下载 &#x1f4a8;使用CDN方式 当然你也可以使用官方的C…

【编程题】【Scratch三级】2021.12 分身术

分身术 1. 准备工作 (1)删除小猫角色、添加角色“Monkey”,Money位于舞台的中心; (2)添加背景Light; (3)新建变量“编号”。 2. 功能实现 (1)程序开始时,Monkey说:“我会分身术!变!!!”2秒; (2)每隔2秒克隆出一个位置随机、大小随机、颜色随机的Monke…

python easygui修改窗口位置

EasyGui是一个十分简单的Python图形界面库&#xff0c;支持窗口文本显示、图片显示、按钮、文本框、选项栏、文件选择等等必要的组件且操作十分简单。但也因如此&#xff0c;导致EasyGui甚至不能手动调整窗口位置、按钮位置、名字等&#xff0c;因为EasyGui是基于Tkinter编写的…

VMware三种网络模式详解

VMware三种网络模式 linux重启网络服务命令&#xff1a; service network restart 一、桥接模式 原理&#xff1a;VMware和宿主机&#xff0c;处于同一网段、两者地位平等。&#xff08;无需虚拟网卡&#xff09; 1.1、使用方法 虚拟网络编辑器 虚拟机设置-适配器 上面两…

<Linux> 编译器与调试器—gcc/g++/gdb 的使用

< Linux > 编译器与调试器—gcc/g/gdb 的使用 文章目录< Linux > 编译器与调试器—gcc/g/gdb 的使用一、Linux编译器 - gcc/g 使用1. 编译程序的四个过程背景知识预处理编译汇编链接2. 链接方式与函数库2.1 动态链接与静态链接2.2.函数库2.3.动态库与静态库3. gcc/…

干货分享:谷歌主动搜索开发客户的万能公式

大家在用谷歌(Google)开发是不是也有以下常见问题&#xff1a; 关键词不准&#xff0c;搜索到的都是零售商&#xff0c;B2C平台搜索到的客户太大&#xff0c;已经被开发多次&#xff0c;开发信不回复搜索到的客户找不到邮箱搜索到的客户与工厂不匹配&#xff0c;无法合作 其实…

车路协同 智能路侧设备网络安全接入技术要求

1 范围 本文件包含智能路侧设备网络安全接入技术要求&#xff0c;包括智能路侧设备连接要求、接入要求、证书管理要求。 本文件适用于智能路侧设备网络安全接入的设计与开发。 2 规范性引用文件 下列文件中的内容通过文中的规范性引用而构成本文件必不可少的条款。其中&…

Simulink永磁同步电机控制仿真:过调制及电流重构

在一些高功率密度的应用场景中&#xff0c;追求极致的电压利用率&#xff0c;这个时候要用到过调制技术&#xff1b;当svpwm工作在过调制区域时&#xff0c;逆变电桥会在一个基波周期内多次达到100%占空比&#xff0c;且较多时间处于较高的占空比&#xff0c;这个时候下桥臂电流…

数据结构系列学习(七) - 链栈(Chain_Stack)

目录 引言&#xff1a; 学习&#xff1a; 代码实现&#xff1a; 头文件&#xff08;Chain_Stack.h&#xff09;&#xff1a; 设置链栈中的元素范型&#xff1a; 链栈的结构体设计&#xff1a; 所有功能函数的声明&#xff1a; 源文件&#xff08;Chain_Stack.cpp&#…

性能测试场景设计之 阶梯性能场景(负载测试场景)

「负载测试&#xff1a;」 逐步增加并发用户数。看服务器的最大拐点区间在哪里。再缩小拐点区间&#xff0c;找出最大并发用户数。 使用方式&#xff1a; 安装 jpgc插件 添加线程组 每次递增10个并发 This group will start&#xff1a;给定当前负载的并发用户数First, wait …

机器学习-集成算法

文章目录集成算法1. 定义2. 具体模型2.1. Bagging2.2. Boosting2.3. Stacking3. 随机森林3.1. 树模型结构3.2. 随机森林的优点3.3. 分类与回归问题3.4. 树模型个数问题3.5. 参数问题(特征重要性)3.6. 可视化展示问题4. 集成基本思想4.1. 硬投票策略步骤4.2. 软投票策略步骤5. B…

【SpringMVC】基础、环境搭建、注解搭建、 and so on……

文章目录SpringMVC【原理】&#xff1a;一、why?&#xff1a;二、环境搭建&#xff08;配置方式&#xff09;&#xff1a;▶1.导入jar包▶2.创建简单测试----创建Controller类继承AbstractController▶3.如何读取Controller文件&#xff0c;创建SpringMVC.xml配置文件&#xf…

使用SPACEDESK时iPad显示Connected-Display OFF解决方法

使用SPACEDESK时iPad显示Connected-Display OFF1. SPACEDESK 概述2. 使用SPACEDESK时iPad显示Connected-Display OFF解决方法结束语1. SPACEDESK 概述 SPACEDESK 是一款网络显示多显示器软件&#xff0c;适用于电脑桌面复制&#xff08;镜像或克隆&#xff09;&#xff0c;能将…

[附源码]java毕业设计代驾服务系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

初识C语言

初识C语言什么是C语言&#xff1a;环境配置&#xff08;VS2019介绍&#xff09;&#xff1a;你的第一个C语言程序常量与变量变量的分类局部变量与全局变量的对比变量的使用&#xff1a;变量的作用域和生命周期&#xff08;重要&#xff09;生命周期常量字符串转义字符注释转义字…

章节1 计算机体系结构

1.2.1-计算机硬件组成-CPU 计算机组成 台式机硬件-内部 台式机硬件-外部结构 CPU Center Processing Unit&#xff08;中央处理器/处理器&#xff09; 常见的电脑处理器&#xff1a; Inetl奔腾8086、酷睿i5 i7 i9&#xff1b;AMD 锐龙 常见的手机处理器&#xff1a; 高通…

SOT-23和SOT-223三极管及MOS管封装区别以及示意图

SOT23封装 三极管 三极管为SOT23封装时&#xff0c;无论是NPN还是PNP。 引脚分布1脚为基极(B)&#xff0c;2脚为发射极(E)&#xff0c;3脚为集电极©。 NPN PNP MOS管 MOS管为SOT23封装时&#xff0c;无论是N-MOS还是P-MOS。 引脚分布1脚为栅极(G)&#xff0c;2脚为源极(S…

Vue3树形控件实现跳转页面

今天想分享的是Vue3中利用element-plus中的树形控件实现跳转页面&#xff0c;做成类似标签页tabs一样的效果。 1、什么是树形控件 树形控件即可以展现层级结构&#xff0c;可以清晰的看到什么需求在哪个项目下&#xff0c;如下图所示 树形控件直通车 2、分析树形控件的基本…