Spring(一)IOC 依赖注入

Spring(一)IOC 依赖注入

1. Spring

Spring -> 春天! 软件行业的春天!

Spring是一个开源的Java/Java EE应用程序框架,它被设计用来简化企业级应用程序的开发。Spring的核心理念是通过提供一系列的服务,帮助开发者更好地管理对象间的依赖关系,以及更好地组织和结构化他们的应用程序代码。

以下是Spring框架的一些关键特性:

  1. 依赖注入(Dependency Injection):Spring框架通过依赖注入(DI)支持松耦合。DI使得组件之间的依赖关系可以通过配置文件或注解进行描述,而不是通过硬编码。

  2. 面向切面编程(Aspect-Oriented Programming):Spring支持面向切面编程,使得诸如日志记录、事务管理、安全等跨越多个对象层次的关注点可以被模块化和组织得更好。

  3. 事务管理:Spring提供了一套抽象接口以统一各种事务管理API,使得开发者可以使用一致的编程模型跨越不同的事务管理API(如JTA、JDBC、Hibernate、JPA等)。

  4. Spring MVC:Spring的Web MVC框架是一个设计良好的、灵活的、强大的Web应用框架,它提供了一种清晰的分离控制器、模型对象、分派器和处理器对象的方式。

  5. 集成支持:Spring提供了对多种技术的集成支持,包括JDBC、Hibernate、JPA、JMS、RMI等。

  6. 测试:Spring提供了对JUnit和TestNG测试框架的一流支持,使得在Spring环境中进行单元测试和集成测试变得非常简单。

Spring的目标是使得Java/Java EE开发变得更加简单,同时也保持了高性能、健壮性和灵活性。

2. IOC 理论

相关博客 分享Iteye的开涛的精彩讲解

2.1 IOC 本质

控制反转loC(lnversion f Control),是一种设计思想,DI(依赖注入)是实现loC的一种方法,也有人认为DI
只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在
程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是: 获得
依赖对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体
Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转
的是loC容器,其实现方法是依赖注入 (Dependency Injection,DI)。

3. HelloSpring

这是我们接触Spring的第一个程序:

老样子,我们先上目录结构!👇

1734966396291.png

Hello.java 的代码:

package top.qwwq.pojo;

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

beans.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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--
    类型 变量名 = new 类型()
    Hello hello = new Hello()

    id = 变量名
    class = new 的对象
    property 相当于给对象的属性设置一个值
-->

<!--    使用Spring来创建对象,在Spring中这些都成为bean-->
    <bean id="hello" class="top.qwwq.pojo.Hello">
<!--
        ref: 引用Spring容器中创建好的对象
        value: 具体的值,基本数据类型
-->
        <property name="str" value="Spring"/>
    </bean>
</beans>

最后再上我们的测试代码:

public class MyTest {
    public static void main(String[] args) {
        // 获取Spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        // 我们的对象现在都在Spring中管理,我们要是用,直接去里面取出来就可以!
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}

​ 可以看出,我们再main方法中并没有new对象而是通过getBean方法来获取到一个对象,这就是Spring中最重要的一个思想之一(IOC 控制反转),我们把对象交给Spring容器,

​ 当我们有需要的时候,就告诉容器:我想要这个对象啦!!!!

​ 容器就会把相应的对象给你,有时还会“贴心”地帮你赋值(这就是 依赖注入 在后面我们会说到), 每一个java类就是一个bean,我们把bean注册到Spring地配置文件中,Spring容器就会帮我们管理对象

4. IOC 创建对象的方式

上代码前,先来目录结构!

1734966420563.png

我们知道,Spring会帮助我们接管对象,但是!Spring到底是怎么帮助我们接管对象的呢?

在beans.xml中写道:

<!--        无参构造-->
    <bean id="user" class="top.qwwq.pojo.User">
        <property name="name" value="EnderKC"/>
     </bean>

<!--    有参构造方法-->
    <bean id="user2" class="top.qwwq.pojo.User" name="userNew,u2">
        <constructor-arg name="name" value="EnderHKC"/>
    </bean>

​ 通过实验得知,Spring也是通过类地构造方法来创建对象。而且默认是用无参构造方法创建对象,使用set方法来给对象注入值。当我们地类中有 有参构造方法 的时候,Spring也可以使用 有参构造方法 创建对象,并且用构造器给对象注入值(后面会提到)。

5. Spring 配置

5.1 别名

<alias name="student" alias="Stu"/>

<bean id="student" class="top.qwwq.pojo.Student"/>

​ 可以通过在beans.xml中利用这种方式来给 已经在beans中注册了地类去别名 (跟MyBatis中不一样!)

5.2 Bean的配置

bean的配置

  • id: bean的唯一表示符,也就是相当于我们学的对象名
  • class: bean 对象所对应的权限定名 : 报名 + 类型
  • name:也是别名,而且name更高级 可以同时取多个别名

5.3 import

1734966443828.png

​ 如果我们刚好同时拥有两个Spring的配置文件,例如:一个用来管理beans,另一个用来管理MyBatis的东西。可以用到这个配置👇

<import resource="spring-dao.xml"/>

在applicationContext.xml中,导入spring-dao.xml的配置,可以让项目的配置看起来更加干净

6. 依赖注入

6.1 构造器注入

可以通过有参构造方法来给对象注入值

<!--有参构造方法-->
<bean id="user2" class="top.qwwq.pojo.User" name="userNew,u2">
    <constructor-arg name="name" value="EnderHKC"/>
</bean>

java的代码:

private String name;

// 有参构造方法
public User(String name){
    this.name = name;
}

用构造器注入的之后,就使用constructor-arg标签

6.2 Set方法注入

<!-- 无参构造-->
<bean id="user" class="top.qwwq.pojo.User">
    <property name="name" value="EnderKC"/>
</bean>

java代码

private String name;

// 无参构造方法
public User(){
    System.out.println("User的无参构造");
}

用set注入,可以使用property标签

6.3 拓展方式注入

假如!我们有一个类有非常多种类的属性,例如:👇

public class Student {
    private String name;
    private Address address;
    private String[] books;
    private List<String> hobbys;
    private Map<String,String> card;
    private Set<String> games;
    private Properties info;
    private String wife;
}

Spring也为我们提供了优雅的依赖注入方式:

    <bean id="student" class="top.qwwq.pojo.Student">
<!--        第一种 普通注入 value-->
        <property name="name" value="EnderKC"/>
<!--        第二种 bean注入 ref-->
        <property name="address" ref="address"/>
<!--        数组注入,ref-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>水浒传</value>
                <value>三国演义</value>
            </array>
        </property>
<!--        List -->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>敲代码</value>
                <value>看电影</value>
                <value>打篮球</value>
            </list>
        </property>
<!--        MAP-->
        <property name="card">
            <map>
                <entry key="身份证" value="111223334556788"/>
                <entry key="银行卡" value="1235678432"/>
            </map>
        </property>
<!--        SET-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>BOB</value>
                <value>COC</value>
            </set>
        </property>
<!--        null-->
        <property name="wife">
            <null/>
        </property>
<!--        Properties-->
        <property name="info">
            <props>
                <prop key="学号">1001</prop>
                <prop key="性别">男</prop>
            </props>
        </property>
    </bean>

6.4 bean的作用域

singleton 默认是单例模式 每获取的对象都是同一个

<bean id="user3" class="top.qwwq.pojo.User" p:name="Ender" p:age="17" scope="singleton"/>

原型模式 获取的每个对象都不相等

<bean id="user4" class="top.qwwq.pojo.User" p:name="Ender" p:age="17" scope="prototype"/>

验证:

// 单例模式 获取的对象是同一个 返回True
User user = (User) context.getBean("user3");
User user2 = (User) context.getBean("user3");
System.out.println(user == user2);
// 原型模式 每次从容器中get的时候都会得到一个新对象 返回false
User user3 = (User) context.getBean("user4");
User user4 = (User) context.getBean("user4");
System.out.println(user3 == user4);

Spring(一)IOC 依赖注入
http://localhost:8090//archives/xv6VQT0s
作者
EnderKC
发布于
2024年12月23日
许可协议