【Spring】IOC基本用法

博客主页:我的主页
欢迎点赞 收藏 留言 欢迎讨论!
本文由 【泠青沼~】 原创,首发于 CSDN
由于博主是在学小白一枚,难免会有错误,有任何问题欢迎评论区留言指出,感激不尽!个人主页


目录

  • 一、向Spring容器中注册Bean
    • 1.1、使用MAVEN注入依赖
    • 1.2、创建实体类
    • 1.3、编写beans.xml文件
    • 1.4、从容器获取 Bean
  • 二、Bean标签中的id和name属性
  • 三、属性注入
    • 3.1、从容器获取 Bean
      • 3.1.1、普通属性注入
      • 3.1.2、 复杂属性注入
    • 3.2、构造器注入
    • 3.3、p 名称空间注入
  • 四、属性自动注入
  • 五、配置文件加载
  • 六、Java 代码配置


一、向Spring容器中注册Bean

1.1、使用MAVEN注入依赖

选择Spring_context,其中Spring-core和Spring-beans都是包含在context中的,core是最基本的模块,beans模块基于core模块,context基于core和beans模块

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>6.0.4</version>
        </dependency>
    </dependencies>

1.2、创建实体类

public class Person {
    private String name;
    private Integer age;
    private Integer gender;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                '}';
    }
    ...省略get和set

1.3、编写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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="com.dong.Person" id="person"/>
</beans>

1.4、从容器获取 Bean

public class demo1 {
    public static void main(String[] args) {
        //这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext cptx = new ClassPathXmlApplicationContext("beans.xml");
        Person person01 = cptx.getBean("person", Person.class);
        Person person02 = cptx.getBean(Person.class);
        Person person03 = (Person) cptx.getBean("person");
        System.out.println(person01);
        System.out.println(person02);
        System.out.println(person03);
    }
}

要注意的是,如果遇到容器中注册有多个类型一样的bean,就不能使用根据类型来注入bean,否则会报错。如果相同类型存在多个 Bean,则会抛出异常
在这里插入图片描述

二、Bean标签中的id和name属性

bean 标签中,可以设置 id,也可以设置 name,一般来说,这两者没有区别。
如果使用 id 的话,则 id 要符合 XML 中关于 ID 的规范,就不能使用一些特殊字符
规则:

  1. 如果同时使用 id 和 name,则两者都生效
 <bean class="com.dong.Person" id="person" name="person2"/>
  1. id 和 name 不能重复。同一个容器中,Bean 的名称是不能重复的。id 和 name 也不能重名。如果重复使用 BeanName,则会抛出异常:
    在这里插入图片描述
  2. name 可以同时定义多个
<bean class="com.dong.Person"  name="person1,person2,person3"/>
<bean class="com.dong.Person"  name="person1 person2 person3"/>
<bean class="com.dong.Person"  name="person1;person2;person3"/>

这个表示给当前 Bean 同时取了三个名字,分别是 person1,person2,person3。当然,name 之间可以使用逗号分隔,也可以使用空格或者分号分隔。
如果是 id,则含义不同:

<bean class="com.dong.Person"  id="person1,person2,person3"/>

此时,就表示这个 Bean 的名称为person1,person2,person3这个整体。

如果没有设置 id 和 name 属性,默认的 beanName 就是类的全路径

    public static void main(String[] args) {
        //这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext cptx = new ClassPathXmlApplicationContext("beans.xml");
        Person bean = (Person)cptx.getBean("com.dong.Person");
        System.out.println(bean);
       
    }

如果存在多个类的实例,并且多个实例都没有配置 id 和 name,默认情况下,beanName 就是 类的全路径#编号

    public static void main(String[] args) {
     	//这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //这行代码,会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        Person person1 = (Person) ctx.getBean("com.dong.Person");
        Person person2 = (Person) ctx.getBean("com.dong.Person#1");
        Person person3 = (Person) ctx.getBean("com.dong.Person#2");
        System.out.println(person1);
        System.out.println(person2);
        System.out.println(person3);
       
    }

三、属性注入

3.1、从容器获取 Bean

这种注入方式,首先是调用类的无参构造方法去创建一个对象出来,然后通过 set 方法为对象的各个属性赋值

3.1.1、普通属性注入

首先定义 User 类:

public class User {
    private String name;
    private String address;
    private Integer age;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", age=" + age +
                '}';
    }
省略set和get方法...

然后在 Spring 的配置文件中进行配置:

<?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 class="org.javaboy.demo.User" id="user">
        <!--通过 set 方法去注入值,本质上,这里最终会调用到对应的 set 方法-->
        <property name="name" value="javaboy"/>
        <property name="address" value="深圳"/>
        <property name="age" value="99"/>
    </bean>
</beans>

本质上,这里最终会调用到对应的 set 方法。
启动容器:

public static void main(String[] args) {
        //这个容器,就是自动去 classpath 下面查找配置文件,并根据该配置文件启动容器
        //这行代码,会加载 Spring 的配置文件,并完成容器的初始化
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        //根据名字获取一个 Bean
        User user = ctx.getBean(User.class);
        System.out.println("user = " + user);
    }

需要注意,XML 中配置的属性名,是通过 get/set 方法推断出来的属性名(Java 内省),不是在类中定义的属性名称

3.1.2、 复杂属性注入

数组、Map、List、Set、Properties、对象
重新定义 User:

public class User {

    private Dog dog;

    private String[] favorites;

    private List<Cat> cats;

    private Map<String, Object> info;

    private Properties job;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", address='" + address + '\'' +
                ", age=" + age +
                ", dog=" + dog +
                ", favorites=" + Arrays.toString(favorites) +
                ", cats=" + cats +
                ", info=" + info +
                ", job=" + job +
                '}';
    }

set和get省略...

在 XML 文件中注入属性值:

        <bean class="com.dong.Dog" id="dog">
                <property name="name" value="小黑"/>
                <property name="age" value="1"/>
        </bean>
        <bean class="com.dong.Cat" id="cat">
                <property name="age" value="2"/>
                <property name="name" value="小米"/>
        </bean>
        <bean class="com.dong.User" id="user">
                <!--通过 set 方法去注入值,本质上,这里最终会调用到对应的 set 方法-->
                <property name="name" value="dong"/>
                <property name="address" value="shanxi"/>
                <property name="age" value="56"/>
                <!--ref 表示引用一个外部的 Bean,一个外部对象-->
                <property name="dog" ref="dog"/>
                <property name="cats">
                        <list>
                                <bean class="com.dong.Cat" name="cat2">
                                        <property name="name" value="xiaobi"/>
                                        <property name="age" value="3"/>
                                </bean>
                                <ref bean="cat"/>
                        </list>
                </property>
                <property name="favorites">
                        <array>
                                <value>羽毛球</value>
                                <value>足球</value>
                                <value>篮球</value>
                        </array>
                </property>
                <property name="info">
                        <map>
                                <entry key="nation" value="汉族"/>
                                <entry key="deu" value="本科"/>
                        </map>
                </property>
                <property name="job">
                        <props>
                                <prop key="slaray">15000</prop>
                                <prop key="engineer">java工程师</prop>
                        </props>
                </property>
        </bean>

3.2、构造器注入

首先,为 User 类提供构造器:

    public User() {
    }

    public User(String name, String address, Integer age, Dog dog, String[] favorites, List<Cat> cats, Map<String, Object> info, Properties job) {
        this.name = name;
        this.address = address;
        this.age = age;
        this.dog = dog;
        this.favorites = favorites;
        this.cats = cats;
        this.info = info;
        this.job = job;
    }

然后在 XML 中注入即可:

    <bean class="com.dong.Dog" id="dog">
        <property name="name" value="小黑"/>
        <property name="age" value="1"/>
    </bean>
    <bean class="com.dong.Cat" id="cat">
        <property name="age" value="2"/>
        <property name="name" value="小米"/>
    </bean>
    <bean class="com.dong.User" id="user">
        <!--通过下标去设置参数-->
        <!--        <constructor-arg index="0" value="lisi"/>-->
        <constructor-arg name="name" value="dong"/>
        <constructor-arg name="address" value="shanxi"/>
        <constructor-arg name="age" value="10"/>
        <constructor-arg name="dog" ref="dog"/>
        <constructor-arg name="cats">
            <list>
                <bean class="com.dong.Cat" name="cat2">
                    <property name="name" value="xiaobi"/>
                    <property name="age" value="3"/>
                </bean>
                <ref bean="cat"/>
            </list>
        </constructor-arg>
        <constructor-arg name="favorites">
            <array>
                <value>羽毛球</value>
                <value>足球</value>
                <value>篮球</value>
            </array>
        </constructor-arg>
        <constructor-arg name="info">
            <map>
                <entry key="nation" value="汉族"/>
                <entry key="deu" value="本科"/>
            </map>
        </constructor-arg>
        <constructor-arg name="job">
            <props>
                <prop key="position">Java工程师</prop>
                <prop key="salary">15000</prop>
            </props>
        </constructor-arg>
    </bean>

3.3、p 名称空间注入

<bean class="com.dong.Dog" id="dog02" p:name="小黄" p:color="黄色"/>

四、属性自动注入

bean 标签中的 autowire 属性有五种

取值 含义
no 默认取值即此。表示不做自动注入,如果有需要注入的值,需要用户明确的手动去指定注入
byName 这个会分析当前 Bean 中的属性,然后去 Spring 容器中查找到同名的属性,并调用 set 方法给该 Bean 中对应的属性赋值
byType 这个会分析当前 Bean 中的属性,然后去 Spring 容器中查找到同类型的属性,并调用 set 方法给该 Bean 中对应的属性赋值。但是需要注意,如果使用这一种,则去查找的 Bean 只能存在一种有效类型
constructor 这个会找到合适的构造方法,通过构造方法给对应的属性注入值
default 这个表示使用父标签中的定义处理
<beans default-autowire="constructor">
    <bean class="com.dong.Cat" id="cat">
        <property name="name" value="小花"/>
        <property name="age" value="10"/>
    </bean>
    <bean class="com.dong.Cat" id="cat2">
        <property name="name" value="小菜"/>
    </bean>
    <bean class="com.dong.User" id="user" autowire="default">
        <property name="name" value="张三"/>
        <property name="age" value="99"/>
    </bean>
</beans>

五、配置文件加载

public class demo01 {
    public static void main(String[] args) {
        FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("src/main/resources/beans.xml");
        User user = ctx.getBean(User.class);
        System.out.println("user = " + user);
    }
}
  • FileSystemXmlApplicationContext:这个是从当前项目根目录下开始去加载配置文件

  • ClassPathXmlApplicationContext:这个是去 classpath 下查找配置文件

六、Java 代码配置

public class JavaConfig {

    /**
     * 这个就表示将当前方法的返回值注册到 Spring 容器中,默认情况下,方法名就是 beanName
     * 如果想自定义 BeanName,则可以在 @Bean 注解中进行定义。
     */
    @Bean("u1")
    User user1(Dog dog) {
        User user = new User();
        user.setName("javaboy");
        user.setAge(99);
        user.setDog(dog);
        return user;
    }

    @Bean
    Dog dog() {
        Dog dog = new Dog();
        dog.setName("阿黄");
        dog.setAge(8);
        return dog;
    }

}
  • 当前类没有添加 @Configuration注解
  • 在一个 @Bean标记的方法中,调用另一个 @Bean标记的方法,对于当前这种情况,默认会直接再次执行该方法,从而导致某一个 Bean 被初始化两次
  • 可以在 Bean 方法中,添加参数,Spring 容器在初始化的时候,会自动从 Spring 容器中查找并处理这个参数

你可能感兴趣的:(Spring源码,spring,java,后端,spring,boot)