spring

发布于:2025-04-18 ⋅ 阅读:(37) ⋅ 点赞:(0)

一、Spring IoC 容器概念

1. 组件和组件管理概念

  • 1.1 什么是组件?

    常规的三层架构处理请求流程:

  • 整个项目就是由各种组件搭建而成的:
  • 1.2 我们的期待?

    • 有人替我们创建组件的对象

    • 有人帮我们保存组件的对象

    • 有人帮助我们自动组装

    • 有人替我们管理事务

    • 有人协助我们整合其他框架

    • ......

  • 1.3 Spring充当组件管理角色(IoC)

    那么谁帮我们完成我们的期待,帮我们管理组件呢?

    当然是Spring 框架了!

    组件可以完全交给Spring 框架进行管理,Spring框架替代了程序员原有的new对象和对象属性赋值动作等!

    Spring具体的组件管理动作包含:

    • 组件对象实例化

    • 组件属性属性赋值

    • 组件对象之间引用

    • 组件对象存活周期管理

    • ...... 我们只需要编写元数据(配置文件)告知Spring 管理哪些类组件和他们的管理即可! 注意:组件是映射到应用程序中所有可重用组件的Java对象,应该是可复用的功能对象!

    • 组件一定是对象

    • 对象不一定是组件 综上所述,Spring 充当一个组件容器,创建、管理、存储组件,减少了我们的编码压力,让我们更加专注进行业务编写!

  • 1.4 组件交给Spring管理优势!

    1. 降低了组件之间的耦合性:Spring IoC容器通过依赖注入机制,将组件之间的依赖关系削弱,减少了程序组件之间的耦合性,使得组件更加松散地耦合。

    2. 提高了代码的可重用性和可维护性:将组件的实例化过程、依赖关系的管理等功能交给Spring IoC容器处理,使得组件代码更加模块化、可重用、更易于维护。

    3. 方便了配置和管理:Spring IoC容器通过XML文件或者注解,轻松的对组件进行配置和管理,使得组件的切换、替换等操作更加的方便和快捷。

    4. 交给Spring管理的对象(组件),方可享受Spring框架的其他功能(AOP,声明式事务管理)等

2. Spring IoC容器和容器实现

组件管理都是交给Spring的IoC容器实现,接下来我们介绍SpringIoC容器!

  • 2.1 普通和复杂容器

    普通容器

    生活中的普通容器

    普通容器只能用来存储,没有更多功能。 程序中的普通容器

    • 数组

    • 集合:List

    • 集合:Set 复杂容器 生活中的复杂容器

    政府管理我们的一生,生老病死都和政府有关。 程序中的复杂容器 Servlet 容器能够管理 Servlet、Filter、Listener 这样的组件的一生,所以它是一个复杂容器。我们即将要学习的Spring IoC 容器也是一个复杂容器。它们不仅要负责创建组件的对象、存储组件的对象,还要负责调用组件的方法让它们工作,最终在特定情况下销毁组件。

    名称 时机 次数
    创建对象 默认情况:接收到第一次请求 修改启动顺序后:Web应用启动过程中 一次
    初始化操作 创建对象之后 一次
    处理请求 接收到请求 多次
    销毁操作 Web应用卸载之前 一次
    总结:Spring管理组件的容器,就是一个复杂容器,不仅存储组件,也可以管理组件之间依赖关系,并且创建和销毁组件等!
  • 2.2 SpringIoC容器介绍

    Spring IoC 容器,负责实例化、配置和组装 bean(组件)。容器通过读取配置元数据来获取有关要实例化、配置和组装组件的指令。配置元数据以 XML、Java 注释或** Java 代码形式**表现。它允许表达组成应用程序的组件以及这些组件之间丰富的相互依赖关系。

  • 上图显示了 Spring 容器工作原理的高级视图。应用程序类与配置元数据相结合,您拥有完全配置且可执行的系统或应用程序。

  • 2.3 SpringIoC容器接口和实现

    SpringIoc容器接口

    org.springframework.beansorg.springframework.context 包是 Spring Framework 的 IoC 容器的基础包。

    BeanFactory 接口提供了一种高级配置机制,能够管理任何类型的对象,它是SpringIoC容器标准化超接口!

    ApplicationContextBeanFactory 的子接口。它补充说:

    • 更容易与 Spring 的 AOP 功能集成

    • 消息资源处理(用于国际化)

    • 特定于应用程序给予此接口实现,例如Web 应用程序的 WebApplicationContext 简而言之, BeanFactory 提供了配置框架和基本功能,而 ApplicationContext 添加了更多特定于企业的功能。 ApplicationContextBeanFactory 的完整超集! ApplicationContext容器实现类

    类型名 简介
    ClassPathXmlApplicationContext 通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象
    FileSystemXmlApplicationContext 通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
    AnnotationConfigApplicationContext 通过读取Java配置类创建 IOC 容器对象
    WebApplicationContext 专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。
  • 2.4 SpringIoC容器管理配置方式

    Spring IoC 容器使用多种形式的配置元数据。此配置元数据表示您作为应用程序开发人员如何告诉 Spring 容器实例化、配置和组装应用程序中的对象。

    1. XML配置方式:是Spring框架最早的配置方式之一,通过在XML文件中定义Bean及其依赖关系、Bean的作用域等信息,让Spring IoC容器来管理Bean之间的依赖关系。该方式从Spring框架的第一版开始提供支持。

    2. 注解方式:从Spring 2.5版本开始提供支持,可以通过在Bean类上使用注解来代替XML配置文件中的配置信息。通过在Bean类上加上相应的注解(如@Component, @Service, @Autowired等),将Bean注册到Spring IoC容器中,这样Spring IoC容器就可以管理这些Bean之间的依赖关系。

    3. Java配置类方式:从Spring 3.0版本开始提供支持,通过Java类来定义Bean、Bean之间的依赖关系和配置信息,从而代替XML配置文件的方式。Java配置类是一种使用Java编写配置信息的方式,通过@Configuration、@Bean等注解来实现Bean和依赖关系的配置。 配置方式的使用场景不同,为了更多体验每种方式,SSM期间,我们使用XML+注解方式为主。SpringBoot期间,我们使用配置类+注解方式为主

  • Spring框架提供了多种配置方式:XML配置方式、注解方式和Java配置类方式

3. Spring IoC / DI概念总结

  • IoC容器

    Spring IoC 容器,负责实例化、配置和组装 bean(组件)。容器通过读取配置元数据来获取有关要实例化、配置和组装组件的指令。

  • IoC(Inversion of Control)控制反转

    IoC 主要是针对对象的创建和调用控制而言的,也就是说,当应用程序需要使用一个对象时,不再是应用程序直接创建该对象,而是由 IoC 容器来创建和管理,即控制权由应用程序转移到 IoC 容器中,也就是“反转”了控制权。这种方式基本上是通过依赖查找的方式来实现的,即 IoC 容器维护着构成应用程序的对象,并负责创建这些对象。

  • DI (Dependency Injection) 依赖注入

    DI 是指在组件之间传递依赖关系的过程中,将依赖关系在容器内部进行处理,这样就不必在应用程序代码中硬编码对象之间的依赖关系,实现了对象之间的解耦合。在 Spring 中,DI 是通过 XML 配置文件或注解的方式实现的。它提供了三种形式的依赖注入:构造函数注入、Setter 方法注入和接口注入。

二、Spring IoC / DI 实现

1.添加依赖

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <context.version>6.0.7</context.version>
        <jupiter.versoon>5.10.1</jupiter.versoon>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${context.version}</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${jupiter.versoon}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.新建Person类

package com.cuihub.ioc;

public class Person {
    public void sayHello(){
        System.out.println("Hello spring");
    }
}

3.新建spring的IOC配置文件

:resources/applicationContext.xml(文件名随意) ,在其中描述Person

<?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="p01" class="com.cuihub.ioc.Person"/>


</beans>

4.测试

从IOC容器当中获取person实例对象

package com.cuihub.ioc;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonTest {
    @Test
    public void test01() {
        //1.获取IOC容器
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2.从IOC容器当中取出Person,获取到的是object需要强转
        Person person = (Person) beanFactory.getBean("p01");

        person.sayHello();
    }

}

三、获取bean的方式

1.Object getBean(id)-------------------------根据id获取

2.T getBean(Class<T>)----------------------根据类型获取

3.T getBean(id,Class<T>)------------------根据id和类型获取

注意点

-根据id获取,可能获取不到,获取不到报错

-根据类型获取,有且唯一(一个个name只能匹配一个class),则获取成功,否则报错。

        因为ioc容器可以创建多个bean实例

package com.cuihub.ioc;

import com.cuihub.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PersonTest {
    @Test
    public void test01() {
        //1.获取IOCrongqi
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");

        //2.从ioc容器当中获取Person
        Person person = (Person) beanFactory.getBean("p01");
        person.sayHello();
    }

    //演示获取bean的方式
    @Test
    public void test02() {
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
        //方式1
        //Person person = (Person)beanFactory.getBean("p01");

        //方式2
        //Person person = beanFactory.getBean(Person.class);
        //person.sayHello();

        //方式3
        Person person = beanFactory.getBean("p01", Person.class);
        person.sayHello();
    }


}

四、Bean属性赋值:setter注入

1.组件类添加属性

package com.cuihub.spring;

/**
 * @version: java version 17
 * @Author: coder Cui
 * @description:
 * @date: 2025-04-16 11:12
 */
public class HappyComponent {


    // 定义一个名为 componentName 的属性,类型为 String
    private String componentName;

    public String getComponentName() {
        return componentName;
    }
    //必须配置set方法,属性设置,ioc容器是通过set方法调用,进行属性赋值!!!
    public void setComponentName(String componentName) {
        this.componentName = componentName;
    }
    // 定义一个名为 happy 的方法,无参数,无返回值
    public void happy() {
    // 输出字符串 "happyComponent happy" 到控制台
        System.out.println("happyComponent happy");
    }
}

2.配置时给属性指定值

<?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">
     
        <!--2.[重要]给bean的属性赋值:setter注入 -->
        <!--property标签:通过组件类的setXxx()方法给组件对象设置属性-->
        <!--name属性:指定属性名(这个属性是getXxx(),setXxx()方法定义的,和成员变量无关)-->
        <!--value属性:指定属性值-->
        <bean id="HappyComponent" class="com.cuihub.spring.HappyComponent">
                <property name="componentName" value="cuihub"/>
        </bean>

</beans>

3.测试属性输出

package com.cuihub.spring;

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @version: java version 17
 * @Author: coder Cui
 * @description:
 * @date: 2025-04-16 11:14
 */
public class IoTest {
    //2.创建IOC容器并配置文件
    @Test
    public void test01() {
        // 创建一个ClassPathXmlApplicationContext对象,用于加载Spring配置文件
        // 这里的"spring-bean-01.xml"是配置文件的名字,位于类路径下
        ClassPathXmlApplicationContext iocContain =
                new ClassPathXmlApplicationContext("spring-bean-01.xml");
        //3.从容器中获取bean
        // 通过getBean方法从IOC容器中获取名为"HappyComponent"的bean,并将其转换为HappyComponent类型
        HappyComponent happyComponent = iocContain.getBean("HappyComponent", HappyComponent.class);
        // 调用HappyComponent对象的happy方法
        happyComponent.happy();
        //获取组件当中的
        System.out.println(happyComponent.getComponentName());//cuihub
    }
}

五、Bean属性赋值:引用其他Bean

1.声明新组件

package com.cuihub.spring;

public class HappyMachine {
    
    private String machineName;
    
    public String getMachineName() {
        return machineName;
    }
    
    public void setMachineName(String machineName) {
        this.machineName = machineName;
    }
}

2.原组件引用新组件

package com.cuihub.spring;

/**
 * @version: java version 17
 * @Author: coder Cui
 * @description:
 * @date: 2025-04-16 11:12
 */
public class HappyComponent {


    // 定义一个名为 componentName 的属性,类型为 String
    private String componentName;
    public String getComponentName() {
        return componentName;
    }
    //必须配置set方法,属性设置,ioc容器是通过set方法调用,进行属性赋值!!!
    public void setComponentName(String componentName) {
        this.componentName = componentName;
    }
    // 定义一个名为 happy 的方法,无参数,无返回值
    public void happy() {
    // 输出字符串 "happyComponent happy" 到控制台
        System.out.println("happyComponent happy");
    }

    //引用新组件
    private HappyMachine happyMachine;

    public HappyMachine getHappyMachine() {
        return happyMachine;
    }

    public void setHappyMachine(HappyMachine happyMachine) {
        this.happyMachine = happyMachine;
    }
}

3.配置新组件

        <!--配置新组件-->
        <bean id="HappyMachine" class="com.cuihub.spring.HappyMachine">
               <property name="machineName" value="why"/>
        </bean>

4.组件之间引用配置

        <!--配置关系-->
        <bean id="HappyComponent" class="com.cuihub.spring.HappyComponent">
                <property name="componentName" value="cuihub"/>
                <property name="happyMachine" ref="HappyMachine"/>
        </bean>

5.测试

package com.cuihub.spring;

import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @version: java version 17
 * @Author: coder Cui
 * @description:
 * @date: 2025-04-16 11:14
 */
public class IoTest {
    //2.创建IOC容器并配置文件
    @Test
    public void test01() {
        // 创建一个ClassPathXmlApplicationContext对象,用于加载Spring配置文件
        // 这里的"spring-bean-01.xml"是配置文件的名字,位于类路径下
        ClassPathXmlApplicationContext iocContain =
                new ClassPathXmlApplicationContext("spring-bean-01.xml");
        //3.从容器中获取bean
        // 通过getBean方法从IOC容器中获取名为"HappyComponent"的bean,并将其转换为HappyComponent类型
        HappyComponent happyComponent = iocContain.getBean("HappyComponent", HappyComponent.class);
        // 调用HappyComponent对象的happy方法
        happyComponent.happy();
        //获取组件当中的
        System.out.println(happyComponent.getComponentName());//cuihub

        //获取另一个bean
        System.out.println(happyComponent.getHappyMachine().getMachineName());//why
    }
}
                

6.注意事项

        6.1声明bean,不分先后顺序,spring容器内部有缓存机制,先实例化后属性赋值!

        6.2ref 容易错写成value,会抛出Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 异常!

        6.3只有声明到ioc容器,方可被其他bean引用!

六: Bean 属性赋值:内部Bean声明(了解)

1.声明内部bean配置

        在bean里面配置的bean就是内部bean,内部bean只能在当前bean内部使用,在其他地方不能使用。

        不会在ioc容器中,实例和存储内部bean,只会缓存类信息,每次获取的时候再实例化!!
 

<!-- 实验五 [重要]给bean的属性赋值:内部bean -->
<bean id="happyComponent5" class="com.atguigu.ioc.HappyComponent">
    <property name="happyMachine">
        <!-- 在一个 bean 中再声明一个 bean 就是内部 bean -->
        <!-- 内部 bean 可以直接用于给属性赋值,可以省略 id 属性 -->
        <bean class="com.atguigu.ioc.HappyMachine">
            <property name="machineName" value="makeHappy"/>
        </bean>
    </property>
</bean>

2.测试读取

@Test
public void testExperiment05() {

    ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-bean-05.xml");

    HappyComponent happyComponent = iocContainer.getBean("happyComponent5", HappyComponent.class);
    //通过外部bean,可以获取专属内部bean
    System.out.println(happyComponent.getHappyMachine().getMachineName());

    //直接获取内部bean,输出! [[报错]]
    //NoSuchBeanDefinitionException: No qualifying bean of type 'com.atguigu.ioc.HappyMachine' available
    HappyMachine happyMachine = iocContainer.getBean(HappyMachine.class);
    System.out.println("happyMachine = " + happyMachine);
}

七: Bean 属性赋值:引入外部Properties配置参数

  1. 实现目标

    将Druid连接池对象交给SpringIoC容器管理!

  2. 加入数据库依赖

<!-- 数据库驱动 和 连接池-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
</dependency>

        3.创建外部属性文件

                文件位置:resources/jdbc.properties

# 配置成你的数据信息
jdbc.user=root
jdbc.password=root
jdbc.url=jdbc:mysql://主机名:端口号/数据库名
jdbc.driver=com.mysql.cj.jdbc.Driver

       4.引入属性文件

<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>

在 IDEA 中引入 Spring 配置文件中名称空间的两种操作方式:

在打字标签名的过程中根据提示选择一个正确的名称空间 对于直接复制过来的完整标签,可以在名称空间上点击,然后根据提示引入

         5.配置连接池信息

        <!-- 引入外部属性文件 -->
        <context:property-placeholder location="classpath:jdbc.properties"/>
        <!-- 实验六 [重要]给bean的属性赋值:引入外部属性文件 -->
        <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
                <property name="url" value="${jdbc.url}"/>
                <property name="driverClassName" value="${jdbc.driver}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
        </bean>

        6.读取测试

@Test
public void testExperiment06() throws SQLException {
    ApplicationContext iocContainer = new ClassPathXmlApplicationContext("spring-bean-06.xml");
    DataSource dataSource = iocContainer.getBean(DataSource.class);
    Connection connection = dataSource.getConnection();
    System.out.println("connection = " + connection);
}


网站公告

今日签到

点亮在社区的每一天
去签到