【Spring】IoC 控制反转、DI 依赖注入、配置文件和bean的作用域

新手小白记录跟着狂神学习Spring的笔记(第4-11集)~

1.控制反转( IoC )

Ioc(控制反转)是Spring的核心,可以使用XML配置,也可以使用注解,甚至0配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据,创建与组织对象存入容器中,程序使用时再从IoC中取出需要的对象。

采用XML配置实现Bean的时候,Bean的定义信息和实现是分离的;而采用注解方式,把Bean的定义信息定义在实现类中,可以实现0配置。

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

2.代码

2.1 Hello实体类

Java 复制代码
public class Hello{
  private String name;

  public String getName(){
    return name;
  }

  public void setName(String name){
    this.name = name;
  }

  public void show(){
    System.out.println("Hello," + name);
  }

}

2.2 XML配置文件

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相当于一个对象-->
    <bean id="hello" class="com.pojo.Hello">
        <!-- 可以添加属性 给name赋值XiaoDouBao-->
        <!-- ref:引用Spring容器中创建好的对象-->
        <!-- value:具体的值-->
        <property name="name" value="XiaoDouBao"/>  
    </bean>

</beans>

2.3 加载配置文件,获取对象

一个或者多个配置文件可以通过 ApplicationContext 提供的构造函数,使容器从这些外部资源加载配置元数据。

Java 复制代码
public static void main(String[] args){
    // 获取Spring的上下文对象
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml") //配置文件的名字
    // 我们的对象现在都在Spring中管理了,要使用时根据配置文件里的id从容器里取出就可以
    Hello hello = (Hello)context.getBean("hello");
    System.out.println(hello.getName);  //输出XiaoDouBao
}

控制:传统的应用程序的对象是由程序本身创建的,使用Spring后,对象是由Spring来创建的。

反转;程序本身不创建对象,而变成被动地接收对象。

依赖注入 :就是利用set方式来注入的,如果把实体类Hello中setName方法注释掉,会报错。所以Spring一定要有set方法。

这就是IoC控制反转依赖注入,对象由Spring来创建、管理、装配!

3.IoC创建对象的方式

1.默认使用无参构造创建对象

2.也可以使用有参构造创建对象

xml 复制代码
<bean id="user" class="com.pojo.User">
        <!-- 2.1 下标赋值-->
        <constructor-arg index="0" value="DouBao"/>  
</bean>

<bean id="user" class="com.pojo.User">
        <!-- 2.2 类型赋值,不建议使用,如果有两个类型相同的属性会报错-->
        <constructor-arg type="java.lang.String" value="豆包"/>  
</bean>

<bean id="user" class="com.pojo.User">
        <!-- 2.3 (重要)直接指定参数名来赋值-->
        <constructor-arg name="name" value="豆小包"/>  
</bean>

在配置文件加载的时候,文件中管理的所有对象就已经初始化到内存中了。内存中各个对象有一份实例

4.Spring配置

4.1 别名

xml 复制代码
<bean id="user" class="com.pojo.User">
        <property name="name" value="XiaoDouBao"/>  
</bean>

<!-- 也可以用别名获取对象-->
<alias name="user" alias="userNew"/>

User user = (User)context.getBean("userNew");也能获取到

4.2 Bean的配置

xml 复制代码
<!-- id:bean的唯一标识符-->
<!-- class:bean所对应的全限定名(包名+类名)-->
<!-- name:也是别名,而且允许取多个别名--> 
    
<bean id="user" class="com.pojo.User" name="user2 u2,u3;u4">
        <property name="name" value="XiaoDouBao"/>  
</bean>

User user = (User)context.getBean("u2"); User user = (User)context.getBean("u3");

User user = (User)context.getBean("u4"); User user = (User)context.getBean("user2");

都可以获取到对象

4.3 import

一般用于团队开发,可以将多个配置文件(例如bean.xml、bean2.xml、bean3.xml)里面注册的所有bean放到一个总的配置文件applicationContext.xml里。

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">
    
    <import resource="bean.xml"/>
    <import resource="bean2.xml"/>
    <import resource="bean3.xml"/>

</beans>

5.依赖注入

bean对象的创建,依赖 于容器;bean对象所有属性,由容器来注入

5.1 创建一个复杂实体类

Java 复制代码
public class Student{
  private String name;
  private Address address;
  private String[] books;
  private List<String> hobbies;
  private Map<String,String> card;
  private Set<String> games;
  private String wife;
  private Properties info;

  //以下省略get和set方法......
}

5.2 演示如何注入

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 id="addr" class="com.pojo.Address"/>
    
    <bean id="student" class="com.pojo.Student">
        <!-- 1.普通值注入-->
        <property name="name" value="XiaoDouBao"/>  
        
        <!-- 2.使用ref,引用Spring容器中创建好的对象-->
        <property name="address" ref="addr"/>  
        
        <!-- 3.数组注入-->
        <property name="books">
            <array>
                <value>哈利波特</value>
                <value>葬送的芙莉莲</value>
                <value>甄嬛传</value>
            </array>                
        </property> 
        
        <!-- 4.List注入-->
        <property name="hobbies">
            <list>
                <value>躺平</value>
                <value>写代码</value>
                <value>健身</value>
            </list>                
        </property> 
        
        <!-- 5.Map注入-->
        <property name="card">
            <map>
                <entry key="IDCard" value="11112222233334444"/>
                <entry key="bankCard" value="123456789012346678990"/>
            </map>                
        </property>
        
        <!-- 6.Set注入-->
        <property name="games">
            <set>
                <value>保卫萝卜4</value>
                <value>王者荣耀</value>
                <value>扫雷</value>
            </set>                
        </property> 
        
        <!-- 7.1 Null注入方式一-->
        <property name="wife">
            <null/>           
        </property> 
        
        <!-- 7.2 Null注入方式二-->
        <property name="wife" value=""/>
        
         <!-- 8.Properties注入-->
        <property name="info">
            <props>
                <prop key="driver">xxxxx</prop>
                <prop key="url">xxx</prop>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>                
        </property> 
    </bean>
    
</beans>

5.3 p命名和c命名

p命名和c命名不能直接使用,需要导入约束。

5.3.1 p命名

在原来配置文件基础上加xmlns:p="http://www.springframework.org/schema/p"

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"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--p命名:相当于properties,简化了注入步骤-->
    <bean id="user" class="com.pojo.User" p:name="Zoe" p:age="22" />
    <!--对比:<property name="name" value="Zoe"/>  -->

</beans>

5.3.2 c命名

在原来配置文件基础上加xmlns:c="http://www.springframework.org/schema/c"

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"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--c命名:实体类要包含有参构造函数,相当于有参构造器注入,contructor-arg-->
    <bean id="user" class="com.pojo.User" c:name="Zoe" p:age="18" />
    <!-- 对比:<constructor-arg name="name" value="Zoe"/>-->
    
</beans>

6.bean的作用域

6.1 singleton 单例模式

<bean id="user2" class="com.pojo.UserT" scope="singleton" />

Spring的默认模式,同一个类内存中只有一个实例对象

Java 复制代码
@Test
public void test(){
    // 获取Spring的上下文对象
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml") 
    UserT user1 = context.getBean("user2",UserT.class);
    UserT user2 = context.getBean("user2",UserT.class);
    System.out.println(user1 == user2);
}

输出:true

6.2 prototype 原型模式

<bean id="user2" class="com.pojo.UserT" scope="prototype" />

每次从容器中get的时候,都会产生一个新对象

Java 复制代码
@Test
public void test(){
    // 获取Spring的上下文对象
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml") 
    UserT user1 = context.getBean("user2",UserT.class);
    UserT user2 = context.getBean("user2",UserT.class);
    System.out.println(user1 == user2);
}

输出:false

参考视频:狂神说4、IOC本质_哔哩哔哩_bilibili11、Bean的作用域_哔哩哔哩_bilibili

相关推荐
神奇小汤圆22 分钟前
浅析二叉树、B树、B+树和MySQL索引底层原理
后端
文艺理科生31 分钟前
Nginx 路径映射深度解析:从本地开发到生产交付的底层哲学
前端·后端·架构
千寻girling32 分钟前
主管:”人家 Node 框架都用 Nest.js 了 , 你怎么还在用 Express ?“
前端·后端·面试
南极企鹅34 分钟前
springBoot项目有几个端口
java·spring boot·后端
Luke君6079736 分钟前
Spring Flux方法总结
后端
define952739 分钟前
高版本 MySQL 驱动的 DNS 陷阱
后端
忧郁的Mr.Li1 小时前
SpringBoot中实现多数据源配置
java·spring boot·后端
暮色妖娆丶2 小时前
SpringBoot 启动流程源码分析 ~ 它其实不复杂
spring boot·后端·spring
Coder_Boy_2 小时前
Deeplearning4j+ Spring Boot 电商用户复购预测案例中相关概念
java·人工智能·spring boot·后端·spring
Java后端的Ai之路2 小时前
【Spring全家桶】-一文弄懂Spring Cloud Gateway
java·后端·spring cloud·gateway