Java:Spring的IOC

138 阅读22分钟

Java:Spring的IOC 测试活动:Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

装配和注入是什么关系

  • 注入包含着装配。注入能注入bean和普通属性,装配是用来bean之间的操作也就是注入bean。

类、Bean、对象、实例的关系

  • image-20220307111406932

    类可以生成对象/实例。Bean只能生成实例。

IOC怎么做到低耦合

  • 外围用工厂模式,工厂里面使用xml解析和反射技术

Spring 的IOC的工作流程是什么?

  1. 先配置xml文件让对象创建出来
  2. 在类中解析xml文件
  3. 通过反射和xml得到的类名将对象创建出来

什么是IOC容器

  • IOC容器底层就是工厂模式

Spring创建IOC容器的两种方式

  • BeanFactory和ApplicationContext

BeanFactory和ApplicationContext的异同是什么?

  • BeanFactory和ApplicationContext都是IOC容器的基本实现。
  • BeanFactory是Spring内部使用的接口。它加载文件的时候不创建对象,只有在对象使用的时候才会创建对象。
  • ApplicationContext是BeanFactory的子接口,提供更多的功能。一般由开发人员使用。在加载配置文件的时候就会创建对象。

BeanFactory和ApplicationContext哪一个推荐使用

  • ApplicationContext更推荐使用。因为在后续web开发的时候,创建对象这种费时费力的操作尽量在服务器启动的时候完成。

ApplicationContext的两个实现类有什么区别

  • image-20220304194859971

  • FileSystemXmlApplicationContext中调用Xml的路径填的是绝对路径

  • ClassPathXmlApplicationContext中调用Xml的路径是调用方法的类的相对路径

什么是IOC操作Bean管理

  • Bean管理指的是Spring创建对象和Spring注入属性

Bean管理的两种方式

  • Xml配置文件实现
  • 注解方式实现

Xml配置文件实现创建对象

image-20220304200858069

  • 在spring的xml文件中使用标签就能创建对象

Xml中的Bean标签有很多属性

  • id 属性:唯一标识,不能和 name 标签相同。
  • class 属性:类全路径(包类路径)
  • name 属性:唯一标识,能使用特殊符号,不能与 id 标签相同。

Xml中Bean标签的注意点

  • 默认使用无参构造函数创建对象。如果类中重写了有参构造函数但是Xml中没有标识会报错。

什么是DI

  • DI就是依赖注入,也是属性注入。可以理解为给类的属性赋值。

常用的属性注入方法有哪些

  • 通过属性的 set 方法来实现
  • 通过有参构造方法来实现

在 Xml 配置文件中怎么给 Bean 怎么通过 set 方法注入属性?

  1. 先创建类的属性和对应的 set 方法

    package com.atguigu.spring5;
    
    /**
     * 演示使用set方法进行注入属性
     */
    public class Book {
        //创建属性
        private String bname;
        private String bauthor;
        private String address;
        //创建属性对应的set方法
        public void setBname(String bname) {
            this.bname = bname;
        }
        public void setBauthor(String bauthor) {
            this.bauthor = bauthor;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public void testDemo() {
            System.out.println(bname+"::"+bauthor+"::"+address);
        }
    }
    
  2. 在 Xml 配置文件中创建对象,在标签中添加 name 属性和 value 属性。它们分别代表类属性的名称属性注入的值。多个属性注入就需要写多个标签并添加对应的 name 属性和 value 属性。

    <!--2 set方法注入属性-->
    <bean id="book" class="com.atguigu.spring5.Book">
        <!--使用property完成属性注入
            name:类里面属性名称
            value:向属性注入的值
        -->
        <property name="bname" value="易筋经"></property>
        <property name="bauthor" value="达摩老祖"></property>
    </bean>
    

在 Xml 配置文件中怎么给 Bean 怎么通过 有参构造方法 注入属性?

  1. 先创建类的属性和对应的 有参构造方法

    package com.atguigu.spring5;
    
    /**
     * 使用有参数构造注入
     */
    public class Orders {
        //属性
        private String oname="";
        private String address;
        //有参数构造
        public Orders(String oname,String address) {
            this.oname = oname;
            this.address = address;
        }
    
        public void ordersTest() {
            System.out.println(oname+"::"+address);
        }
    }
    
  2. 在 Xml 配置文件中创建对象,在 标签中添加 name 属性和 value 属性。它们分别代表类属性的名称属性注入的值。多个属性注入就需要写多个 标签并添加对应的 name 属性和 value 属性。

    <!--3 有参数构造注入属性-->
    <bean id="orders" class="com.atguigu.spring5.Orders">
        <!--使用constructor-arg完成属性注入
            name:类里面属性名称
            value:向属性注入的值
        -->    
        <constructor-arg name="oname" value="电脑"></constructor-arg>
        <constructor-arg name="address" value="China"></constructor-arg>
    </bean>
    
  3. 了解。在 标签中还可以添加 index 属性和 value 属性。

<!--3 有参数构造注入属性-->
<bean id="orders" class="com.atguigu.spring5.Orders">
    <!--使用property完成属性注入
        index:类里面属性的下标
        value:向属性注入的值
    -->
    <constructor-arg index="0" value="电脑"></constructor-arg>
    <constructor-arg index="1" value="China"></constructor-arg>
</bean>

什么是字面量

  • 类中的属性在声明的时候初始化
  • 类中的属性在 Xml 配置文件中的属性注入
  • 可以理解为对象中某些属性声明时初始化。

怎么在 Xml 配置文档中给属性初始化一个 null

  • 在 set 方法中把标签中的 value 属性去除,并填入一个 标签。

    <!--null值-->
    <property name="address">
        <null/>
    </property>
    

怎么在 Xml 配置文件中给属性带有特殊符号的初始化

  • 在 set 方法中把标签中

    • 把 value 属性里写入特殊符号的转义符号

    • 把标签中的 value 属性去除,填入一个标签。在标签中填入

      <!--属性值包含特殊符号
          1 把<>进行转义 &lt; &gt;
          2 把带特殊符号内容写到CDATA
      -->
      <property name="address">
          <value><![CDATA[特殊符号的value值]]></value>
      </property>
      

怎么在 Xml 配置文件中给一个对象注入外部 Bean

  • 有两个包,分别是 Service 和 Dao

    Service 包中包含了 UserService 类

    Dao 包含了 UserDao 接口和它的实现类 UserDaoImpl

    UserService 类里调用 UserDao 类,通过多态所以使用了 UserDaoImpl 里的方法

    所以我们需要在 UserService 类调用 UserDao 类

    image-20220304224240058

    UserService 类

    package com.atguigu.spring5.service;
    
    import com.atguigu.spring5.dao.UserDao;
    import com.atguigu.spring5.dao.UserDaoImpl;
    
    public class UserService {
    
        //创建UserDao类型属性,生成set方法
        private UserDao userDao;
        public void setUserDao(UserDao userDao) {
            this.userDao = userDao;
        }
    
        public void add() {
            System.out.println("service add...............");
            userDao.update();
        }
    }
    

    UserDao 类

    package com.atguigu.spring5.dao;
    
    public interface UserDao {
        public void update();
    }
    

    UserDaoImpl 类

    package com.atguigu.spring5.dao;
    
    public class UserDaoImpl implements UserDao {
    
        @Override
        public void update() {
            System.out.println("dao update...........");
        }
    }
    
  • 方法

    1. 先在要调用的类里创建一个被调用类的属性,并给出对应的 set 方法

      package com.atguigu.spring5.service;
      
      import com.atguigu.spring5.dao.UserDao;
      import com.atguigu.spring5.dao.UserDaoImpl;
      
      public class UserService {
      
          //创建UserDao类型属性,生成set方法
          private UserDao userDao;
          public void setUserDao(UserDao userDao) {
              this.userDao = userDao;
          }
      
          public void add() {
              System.out.println("service add...............");
              userDao.update();
          }
      }
      
    2. 在 Xml 配置文件中,创建一个调用类的对象和一个被调用类的对象,在调用类对象的标签中添加 name 和 ref 属性。name 和 ref 属性分别代表 被调用类的属性名 和 被调用类id。

      特别注意,这里使用了多态所以被调用的 name 是 userDao,被调用类 id 是 userDaoImpl。

      <!--1 service和dao对象创建-->
      <bean id="userService" class="com.atguigu.spring5.service.UserService">
          <!--注入userDao对象
              name属性:类里面属性名称
              ref属性:创建userDao对象bean标签id值
          -->
          <property name="userDao" ref="userDaoImpl"></property>
      </bean>
      <bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>
      

      上面这一步等同于。注意 UserDao userDao = new UserDaoImpl(); 这一句就代表了 name 和 id。

      package com.atguigu.spring5.service;
      
      import com.atguigu.spring5.dao.UserDao;
      import com.atguigu.spring5.dao.UserDaoImpl;
      
      public class UserService {
          public void add() {
              System.out.println("service add...............");
              UserDao userDao = new UserDaoImpl();
              userDao.update();
          }
      }
      

怎么在 Xml 配置文件中给对象注入内部 Bean

  • 一个班主任老师带领多个学生,每个学生都对应一个班主任老师。

    所以我们可以在学生的属性中添加班主任老师类

    image-20220305115859340

    所以我创建了 Teacher 类和 Student 类,下面是代码实现。

    Teacher 类

    package cn.hyz.bean;
    
    /**
     * @author workplace
     * @date 2022/3/5 11:28
     */
    public class Teacher {
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Teacher{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    Student 类

    package cn.hyz.bean;
    
    import com.sun.corba.se.impl.orb.ParserTable;
    
    /**
     * @author workplace
     * @date 2022/3/5 11:28
     */
    public class Student {
        private String name;
        private String nation;
        private Teacher teacher;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setNation(String nation) {
            this.nation = nation;
        }
    
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
    
        public void say() {
            System.out.println(name + "  " + nation + "  " + teacher.toString());
        }
    }
    
  • 我们现在通过 Xml 配置文件创建一个 Student 类的对象

    1. 现在 Student 中创建一个 Teacher 类的属性

    2. 在 Xml 配置文件中,创造一个 Student 类的对象,并且在 teacher 属性中嵌套了 Teacher 类的对象。

          <property name="teacher">
              <bean class="cn.hyz.bean.Teacher" id="teacher">
                  <property name="name" value="老师"></property>
              </bean>
          </property>
      
      <?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="student" class="cn.hyz.bean.Student">
              <property name="name" value="何雅梓"></property>
              <property name="nation" value="中国"></property>
              <property name="teacher">
                  <bean class="cn.hyz.bean.Teacher" id="teacher">
                      <property name="name" value="老师"></property>
                  </bean>
              </property>
          </bean>
      </beans>
      

级联赋值是什么

  • 一个班主任老师带领多个学生,每个学生都对应一个班主任老师。

    所以我们可以在 Student 的属性中添加 Teacher

    Teacher类

    package cn.hyz.bean;
    
    /**
     * @author workplace
     * @date 2022/3/5 16:26
     */
    public class Teacher {
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String say() {
            return ("我的老师是:" + name);
        }
    }
    

    Student类

    package cn.hyz.bean;
    
    /**
     * @author workplace
     * @date 2022/3/5 16:26
     */
    public class Student {
        private String name;
        private int age;
        private Teacher teacher;
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Teacher getTeacher() {
            return teacher;
        }
    
        public void setTeacher(Teacher teacher) {
            this.teacher = teacher;
        }
    
        public void say() {
            System.out.println("我的名字是:" + name + ",我的年龄是:" + age + teacher.say());
        }
    }
    
  • 级联赋值就是类中要使用另一个类的属性,所以要获取和修改另一个类的属性。

  • 我们现在通过 Xml 配置文件创建一个 Student 类的对象

    1. 我们先在创建一个 Teacher 类的属性和对应的 get set 方法

    2. 再创建 Student 类,并加入 Teacher 类属性。

    3. 创建 Xml 配置文件

      在 Student 对象的 的标签里创建 name 属性和 value 属性。下面就是级联赋值的例子。name 属性里填入的是 外部 Bean.属性名,value 属性里填入的是 修改的值

      image-20220305165628772

      <?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="teacher" class="cn.hyz.bean.Teacher">
              <property name="name" value="何冠德"></property>
          </bean>
          <bean id="student" class="cn.hyz.bean.Student">
              <property name="name" value="何雅梓"></property>
              <property name="age" value="21"></property>
              <property name="teacher" ref="teacher"/>
              <property name="teacher.name" value="级联赋值"></property>
          </bean>
      </beans>
      

注入外部Bean 和 注入内部Bean 和 级联赋值

  • 注入外部Bean

    • 注入外部Bean是通过 Xml 配置文件创建了 类A 和 类B,然后 类B 作为一个属性注入 类A里面。

      就是有一个类A和一个类B。类B在类A中是属性并有对应的set方法。先创建类A和类B对象。在把类B作为实参传入类A的set方法,就可以在类A中调用类B的属性和方法了。

      image-20220305171842069

      	<bean id="类A" class="类A地址">
              <property name="属性a的名称" value="属性a的值"></property>
              <property name="类B名称lb" ref="类B的id"></property>
          </bean>
      	<bean id="类B" class="类B地址">
              <property name="属性b的名称" value="属性b的值"></property>
          </bean>
      

      在 Java 中用代码实现就是

      class A {
          private int a;
          private B lb;
      
          public void setA(int a) {
              this.a = a;
          }
      
          public void setLb(B lb) {
              this.lb = lb;
          }
      
          public void testSay() {
              System.out.println(a + "::" + lb.b);
          }
      }
      
      class B {
          private int b;
      
          public void setB(int b) {
              this.b = b;
          }
      }
      
      @Test
      public void test() {
          A a = new A();
          a.setA(1);
      
          B b = new B();
          b.setB(2);
      
          a.setLb(b);
      
          a.testSay();
      }
      
  • 注入内部Bean

    • 注入外部Bean是通过 Xml 配置文件创建了 类A ,然后 类B 作为一个属性在 类A 里创建。

      先创建类A和A的内部类类B。类B在类A中是属性并有对应的set方法。通过在类A的方法中创建类B的对象就可以调用类B的属性和方法。image-20220305173152283

      	<bean id="类A" class="类A地址">
              <property name="属性a的名称" value="属性a的值"></property>
              <property name="类B名称lb">
                  <bean id="类B" class="类B地址">
                      <property name="属性b的名称" value="属性b的值"></property>
                  </bean>
              </property>
          </bean>
      

      在 Java 中用代码实现

      class A {
          private int a;
          private B bl;
      
          class B {
              private int b;
      
              public void setB(int b) {
                  this.b = b;
              }
          }
      
          public void setBl() {
              B lb = new B();
              lb.setB(2);
              this.bl = lb;
          }
      
          public void setA(int a) {
              this.a = a;
          }
      
          public void testSay() {
              B b = new B();
              b.setB(2);
              System.out.println(a + "::" + bl.b);
          }
      }
      
      @Test
      public void test() {
          A a = new A();
          a.setA(1);
          a.setBl();
          a.testSay();
      }
      
    • 级联赋值

      • 注入外部Bean是通过 Xml 配置文件创建了 类A 和 类B,然后 类B 作为一个属性注入 类A里面。类A 对 类B 有 get set 方法。这样子就能获取了 类A 中的 类B 然后调用 类B 的 set 方法来修改 类B 的属性。

        image-20220305191758871

        	<bean id="类A" class="类A地址">
                <property name="属性a的名称" value="属性a的值"></property>
                <property name="类B名称lb" ref="类B的id"></property>
                <property name="类B名称.属性名b" value="属性b的值"></property>
            </bean>
        	<bean id="类B" class="类B地址">
                <property name="属性b的名称" value="属性b的值"></property>
            </bean>
        

        在 Java 中用代码实现

        class A {
            private int a;
            private B lb;
        
            public void setA(int a) {
                this.a = a;
            }
        
            public B getLb() {
                return lb;
            }
        
            public void setLb(B lb) {
                this.lb = lb;
            }
        
            public void testSay() {
                System.out.println(a + "::" + lb.b);
            }
        }
        
        class B {
            private int b;
        
            public void setB(int b) {
                this.b = b;
            }
        }
        
        @Test
        public void test() {
            A a = new A();
            a.setA(1);
        
            B b = new B();
            b.setB(1);
        
            /* 级联赋值就是获取了类A中的类B然后调用类B的set方法来修改类B的属性 */
            a.setLb(b);
            a.getLb().setB(2);
        
            a.testSay();
        }
        

Xml 配置文件中怎么注入数组、List、Map 和 Set 属性

  • 在类中有着数组、List、Map 和 Set 类型的属性,我们可以在 Xml 配置文件中去创建对象并注入属性

    示范类

    package cn.hyz.bean;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:29
     * 创建出 数组、list、map、set 类型的属性,并给出对应的 set 方法
     */
    public class ArrayBean {
        private String[] var1;
        private List<String> var2;
        private Map<String,String> var3;
        private Set<String> var4;
    
        public void setVar1(String[] var1) {
            this.var1 = var1;
        }
    
        public void setVar2(List<String> var2) {
            this.var2 = var2;
        }
    
        public void setVar3(Map<String, String> var3) {
            this.var3 = var3;
        }
    
        public void setVar4(Set<String> var4) {
            this.var4 = var4;
        }
    
        public void test() {
            System.out.println(Arrays.toString(var1));
            System.out.println(var2);
            System.out.println(var3);
            System.out.println(var4);
        }
    }
    

    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="arrayBean" class="cn.hyz.bean.ArrayBean">
            <!--数组属性注入-->
            <property name="var1">
                <array>
                    <value>var1_1</value>
                    <value>var1_2</value>
                </array>
            </property>
            <!--list属性注入-->
            <property name="var2">
                <list>
                    <value>var2_1</value>
                    <value>var2_2</value>
                </list>
            </property>
            <!--map属性注入-->
            <property name="var3">
                <map>
                    <entry key="var3_1_1" value="var3_1_2"></entry>
                    <entry key="var3_2_1" value="var3_2_2"></entry>
                </map>
            </property>
            <!--set属性注入-->
            <property name="var4">
                <set>
                    <value>var4_1</value>
                    <value>var4_2</value>
                </set>
            </property>
        </bean>
    </beans>
    

    测试类

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.lang.annotation.Target;
    import java.util.Arrays;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:34
     */
    public class ArrayBeanTest {
        @Test
        public void test() {
            ApplicationContext context
                    = new ClassPathXmlApplicationContext("bean7.xml");
            ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class);
            arrayBean.test();
        }
    }
    

    测试结果

    [var1_1, var1_2]
    [var2_1, var2_2]
    {var3_1_1=var3_1_2, var3_2_1=var3_2_2}
    [var4_1, var4_2]
    

    可以看到注入的属性全部输出了。表示 Xml 配置文件注入属性成功


Xml 配置文件中怎么在集合里面设置对象类型值

  • 示范类

    集合中要用到的类

    package cn.hyz.bean;
    
    /**
     * @author workplace
     * @date 2022/3/6 11:08
     */
    public class Bean {
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Bean{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    集合使用类

    package cn.hyz.bean;
    
    import java.util.List;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:29
     * 创建出 数组、list、map、set 类型的属性,并给出对应的 set 方法
     */
    public class ArrayBean {
        /**
         * 生成一个泛型是 Bean 类的 List 类型的属性并给出对应的 set 方法
         */
        private List<Bean> beanList;
    
        public void setBeanList(List<Bean> beanList) {
            this.beanList = beanList;
        }
    
        public void test() {
            System.out.println(beanList);
        }
    }
    

    Xml 配置文件注入属性。注意这里在 List 中的属性注入用的标签是 用 bean 属性指向对象的 id 属性。

    <?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">
    
        <!--在集合里面设置对象类型值-->
    
        <!--1. 创建多个 Bean 对象-->
        <bean id="bean1" class="cn.hyz.bean.Bean">
            <property name="name" value="bean1"/>
        </bean>
        <bean id="bean2" class="cn.hyz.bean.Bean">
            <property name="name" value="bean2"/>
        </bean>
    
        <!--2. 在 ArrayBean 中对 List 类型属性注入,用 ref 中的 bean 属性来指向注入的 Bean 元素-->
        <bean id="arrayBean" class="cn.hyz.bean.ArrayBean">
            <property name="beanList">
                <list>
                    <ref bean="bean1"></ref>
                    <ref bean="bean2"></ref>
                </list>
            </property>
        </bean>
    </beans>
    

    测试类

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:34
     */
    public class ArrayBeanTest {
        @Test
        public void test() {
            ApplicationContext context
                    = new ClassPathXmlApplicationContext("bean7.xml");
            ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class);
            arrayBean.test();
        }
    }
    

    结果

    [Bean{name='bean1'}, Bean{name='bean2'}]
    

    可以看到注入的属性全部输出了。表示 Xml 配置文件注入属性成功。


Xml 配置文件中怎么把集合注入部分提取出来

  • 示范类

    集合中要用到的类

    package cn.hyz.bean;
    
    /**
     * @author workplace
     * @date 2022/3/6 11:08
     */
    public class Bean {
        private String name;
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Bean{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    

    集合使用类

    package cn.hyz.bean;
    
    import java.util.List;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:29
     * 创建出 数组、list、map、set 类型的属性,并给出对应的 set 方法
     */
    public class ArrayBean {
        /**
         * 生成一个泛型是 Bean 类的 List 类型的属性并给出对应的 set 方法
         */
        private List<Bean> beanList;
    
        public void setBeanList(List<Bean> beanList) {
            this.beanList = beanList;
        }
    
        public void test() {
            System.out.println(beanList);
        }
    }
    

    Xml 配置文件注入属性。

    1. 首先进行名称导入
    2. 然后 <util:类型></util:类型> 标签进行集合提取,选择类型之后用 id 属性进行标识
    3. 在对象中进行属性注入,通过 ref 属性指向集合的 id 就可以进行属性注入了。
    <?xml version="1.0" encoding="UTF-8"?>
    <!--1. 名称空间引入
           xmlns:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
        -->
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
        
        <!--2. 集合注入部分提取,在 util:类型并用 id 属性标识-->
        <util:list id="list">
            <value>"var1"</value>
            <value>"var2"</value>
            <value>"var3"</value>
            <value>"var4"</value>
            <value>"var5"</value>
        </util:list>
    
        <!--3. 对象的属性注入,ref 属性用集合提取的 id 作为识别-->
        <bean id="arrayBean" class="cn.hyz.bean.ArrayBean">
            <property name="var2" ref="list"></property>
        </bean>
    </beans>
    

    测试类

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:34
     */
    public class ArrayBeanTest {
        @Test
        public void test() {
            ApplicationContext context
                    = new ClassPathXmlApplicationContext("bean7.xml");
            ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class);
            arrayBean.test();
        }
    }
    

    结果

    ["var1", "var2", "var3", "var4", "var5"]
    

    可以看到注入的属性全部输出了。表示 Xml 配置文件注入属性成功。


什么是工厂Bean(Factory Bean)

  • 一种特殊的 bean,在 xml 文件中配置的,用来生成新的 bean 的加工厂,通过 getObject() 方法可以获取其生产的新 bean,如果想获取该工厂 bean 本身,需要使用类似于getBean("&" + beanName)的样式。

工厂 Bean(Factory Bean)和普通 Bean 有什么区别

  • 普通 Bean 在 Xml 配置文件中定义的 Bean 类型就是返回类型,即通过 Xml 配置文件创建出来的对象的类型。其中的 ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class);ArrayBean就是返回类型。
  • 工厂Bean(Factory Bean)在 Xml 配置文件中定义的 Bean 类型可以和返回类型不同。

如何实现工厂 Bean

  1. 创建实现类并实现 FactoryBean<Object> 接口并重写方法。

    package cn.hyz.factoryBean;
    
    import cn.hyz.bean.ArrayBean;
    import org.springframework.beans.factory.FactoryBean;
    
    import java.util.ArrayList;
    
    /**
     * @author workplace
     * @date 2022/3/6 16:56
     * 创建工厂 Bean,需要实现 FactoryBean<Object> 接口并重写方法。
     * 将接口后面的 <Object> 填写为想要通过工厂 Bean 去获取的类
     */
    public class Bean implements FactoryBean<ArrayBean> {
        /**
         *  然后修改 getObject() 的类型和返回值即可获取到想要的类
         * @return 想要的类
         * @throws Exception
         */
        @Override
        public ArrayBean getObject() throws Exception {
            ArrayBean arrayBean = new ArrayBean();
            ArrayList<String> strings = new ArrayList<>();
            strings.add("1");
            strings.add("2");
    
            arrayBean.setVar2(strings);
            return arrayBean;
        }
    
        @Override
        public Class<?> getObjectType() {
            return null;
        }
    
        @Override
        public boolean isSingleton() {
            return FactoryBean.super.isSingleton();
        }
    }
    
  2. 然后在 Xml 配置文件中创建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 class="cn.hyz.factoryBean.Bean" id="bean"></bean>
    
    </beans>
    
  3. 最后再测试类将对象创建出来。我们传入的 Class对象 和 创建类型 也需要修改成我们想要的那个类。

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author workplace
     * @date 2022/3/6 17:02
     */
    public class BeanTest {
        @Test
        public void test() {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
            /**
             * 这里因为是用了工厂 bean 并且修改 getObject() 的类型和返回值
             * 所以我们传入的 Class对象 和 创建类型 也需要修改成我们想要的那个类
             */
            ArrayBean bean = context.getBean("bean", ArrayBean.class);
            bean.test();
        }
    }
    
  4. 测试结果

    [1, 2]
    
  5. 补充:想要的那个类的代码

    package cn.hyz.bean;
    
    import java.util.List;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:29
     */
    public class ArrayBean {
        private List<String> var2;
    
        public void setVar2(List<String> var2) {
            this.var2 = var2;
        }
    
        public void test() {
            System.out.println(var2);
        }
    }
    

Bean 的作用域是什么

  • 在 Spring 中,bean 作用域用于确定哪种类型的 bean 实例应该从 Spring 容器中返回给调用者。

  • 作用域描述
    singleton在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的默认值。
    prototype每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行newXxxBean()。
    request每次HTTP请求都会创建一个新的Bean,该作用域仅适用于web的Spring WebApplicationContext环境。
    session同一个HTTP Session共享一个Bean,不同Session使用不同的Bean。该作用域仅适用于web的Spring WebApplicationContext环境。
    application限定一个Bean的作用域为ServletContext的生命周期。该作用域仅适用于web的Spring WebApplicationContext环境。
  • 目前常用的是 singleton 和 prototype。默认是 singleton 作用域。

  • singleton 作用阈测试

    测试类

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author workplace
     * @date 2022/3/6 17:02
     */
    public class BeanTest {
        @Test
        public void test() {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
            // 同时创造两个对象看地址是否相同
            ArrayBean bean1 = context.getBean("bean", ArrayBean.class);
            ArrayBean bean2 = context.getBean("bean", ArrayBean.class);
            System.out.println(bean1);
            System.out.println(bean2);
        }
    }
    

    结果

    cn.hyz.bean.ArrayBean@1e7c7811
    cn.hyz.bean.ArrayBean@1e7c7811
    

如何设置作用域

  • 在 Xml 配置文件中我们对于 <bean></bean> 标签里面添加 scope 属性,就可以选择作用域了

    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 标签里添加了 scope 属性并选择了 prototype-->
        <bean class="cn.hyz.factoryBean.Bean" id="bean" scope="prototype"></bean>
    </beans>
    

    测试类

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author workplace
     * @date 2022/3/6 17:02
     */
    public class BeanTest {
        @Test
        public void test() {
            ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
            ArrayBean bean1 = context.getBean("bean", ArrayBean.class);
            ArrayBean bean2 = context.getBean("bean", ArrayBean.class);
            System.out.println(bean1);
            System.out.println(bean2);
        }
    }
    

    结果

    cn.hyz.bean.ArrayBean@4923ab24
    cn.hyz.bean.ArrayBean@44c8afef
    

    可以看出两个对象的地址都不一样。


singleton 作用域和 prototype 作用域的区别是什么?

  • singleton 表示单实例,prototype 表示多实例
  • singleton 是在加载 Xml 配置文件的时候就创建单实例对象。而 prototype 则是在调用 getBean()方法的时候才会创建多实例对象。

Spring 生命周期是什么

  1. 通过无参构造器创建 bean 实例
  2. 通过 Xml 配置文件为 bean 注入属性和对其他 bean 引用(调用 set 方法)
  3. 调用 bean 初始化方法(需要配置初始化的方法)
  4. 使用 bean 生成对象
  5. 容器关闭,调用 bean 的销毁方法(需要配置销毁的方法)
  • 例子

    package cn.hyz.bean;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:29
     */
    public class ArrayBean {
        private String var2;
    
        /**
         * 默认自动生成无参构造方法,为了演示所以写了
         */
        public ArrayBean() {
            System.out.println("第一步:执行无参构造方法创建 bean 实例");
        }
    
        public void setVar2(String var2) {
            this.var2 = var2;
            System.out.println("第二步:调用 set 方法设置属性值");
        }
    
        /**
         * 手动创建初始化方法
         */
        public void initMethod() {
            System.out.println("第三步:执行初始化方法");
        }
    
        /**
         * 手动创建销毁方法
         */
        public void destroyMethod() {
            System.out.println("第五步:执行销毁的方法");
        }
    
        public void test() {
            System.out.println(var2);
        }
    }
    

    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">
    
        <!--添加 init-method destroy-method 属性-->
        <bean id="arrayBean" class="cn.hyz.bean.ArrayBean" init-method="initMethod" destroy-method="destroyMethod">
            <property name="var2" value="123abc"></property>
        </bean>
    </beans>
    

    测试类

    package cn.hyz.beanTest;
    
    import cn.hyz.bean.ArrayBean;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * @author workplace
     * @date 2022/3/6 10:34
     */
    public class ArrayBeanTest {
        @Test
        public void test() {
            ApplicationContext context
                    = new ClassPathXmlApplicationContext("bean7.xml");
            ArrayBean arrayBean = context.getBean("arrayBean", ArrayBean.class);
            System.out.println("第四步,获取创建 bean 实例对象");
            System.out.println(arrayBean);
            /**
             * 手动让 bean 实例销毁。
             */
            ((ClassPathXmlApplicationContext) context).close();
        }
    }
    

    结果

    第一步:执行无参构造方法创建 bean 实例
    第二步:调用 set 方法设置属性值
    第三步:执行初始化方法
    第四步,获取创建 bean 实例对象
    cn.hyz.bean.ArrayBean@c81cdd1
    第五步:执行销毁的方法
    

什么是后置处理器

  • 后置处理器就是在 bean 对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。
    1. 通过无参构造器创建 bean 实例
    2. 通过 Xml 配置文件为 bean 注入属性和对其他 bean 引用(调用 set 方法)
    3. 把 bean 实例传递 bean 后置处理器的方法:postProcessBeforeInitialization(Object bean, String beanName)
    4. 调用 bean 初始化方法(需要配置初始化的方法)
    5. 把 bean 实例传递 bean 后置处理器的方法:postProcessAfterInitialization(Object bean, String beanName)
    6. 使用 bean 生成对象
    7. 容器关闭,调用 bean 的销毁方法(需要配置销毁的方法)

如何创建后置处理器

  • 创建类,实现接口 BeanPostProcessor 并重写方法即可
  • 然后在 Xml 配置文件中创建 Bean,就会为这个 Xml 配置文件中的所有 Bean 创建后置处理器。当创建 Bean 对象并运行的时候,就会在调用初始化之前和之后去调用后置处理器的重写方法,利于程序员添加自己的逻辑。

Xml 自动装配

  • 当一个 bean需要用到其他bean作为属性的时候,不再需要手动外部注入而是会自动注入。

    autowire属性包含了byTypebyName两种。

    这里引用了spring——自动装配【非常详细】 - 白熊啊 - 博客园 (cnblogs.com)

    1.byName

    设置autowire属性为byName,那么Spring会根据class属性找到实体类,然后查询实体类中所有setter方法的名字,根据setter方法后面的名字(例如SetDog,则setter方法后面的名字为dog)再到配置文件中寻找一个与该名字相同id的Bean,注入进来

    image-20220307124258550

    2.byType

    设置autowire属性为byType,那么Spring会自动寻找一个与该属性类型相同的Bean,注入进来。

    image-20220307124324805


IoC基于注解操作bean管理

  1. 什么是注解

    • 什么是注解

      • 注解是特殊格式的代码
    • 注解的使用范围是多大啊

      • 注解能在类上使用;能在方法上使用;能在属性上使用
    • 为什么使用注解

      • 能让 Xml 配置文件更加的简洁
  2. Spring针对Bean管理中创建对象提供了四个注解

    1. @Component

    2. @Service

    3. @Controller

    4. @Repository

    • 四个注解功能都是一样的,都可以用来创建bean实例
  3. 基于注解方式实现对象创建

    1. 第一步:引入依赖

      image-20220307171753522

    2. 第二步:开启组件扫描

      1. 第一步: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:context="http://www.springframework.org/schema/context"
               xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        

        image-20220307173621430

      2. 第二步:开启组件扫描。

        通过创建**<context:component-scan></context:component-scan>**标签,选择属性(base-package) 填入包名,通过单个或多个达到开启组件扫描的结果。

        如果是同一目录下的多个包,1.2和1.3的效果是一样的。

        <!--开启组件扫描-->
        <!--1.1 单个包开启组件扫描
        属性(base-package)中填入单个package.path-->
        <context:component-scan base-package="com.atguigu.spring5.testdemo"></context:component-scan>
        
        <!--1.2 多个包同时开启组件扫描
        属性(base-package)中填入多个package.path,不同package.path之间用','隔开-->
        <context:component-scan
                base-package="com.atguigu.spring5.dao ,com.atguigu.spring5.service"></context:component-scan>
        
        <!--1.3 多个包同时开启组件扫描
        属性(base-package)中填入多个package的同一个上层目录-->
        <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
        

        image-20220307174154733

      3. 第三步:创建类,在类上添加创建对象的注解。

        这里创建了一个名叫 UserService 的类并且使用了 @Component 的注解来创建对象。 @Component 里的属性 (value) 可以省略,默认是类名的小驼峰。

        @Component(value = "userService") 的写法和 <bean id="value填的值" calss="package.path.className"></bean> 的写法是类似的

        package com.atguigu.spring5.service;
        
        import org.springframework.stereotype.Component;
        
        /**
         * @author workplace
         * @date 2022/3/7 17:40
         * 1. @Component(value = "userService") 的写法和 <bean id="value填的值" calss="package.path.className"></bean> 的写法是类似的
         * 2. @Component(value = "userService") 的属性 (value) 可以省略,默认是 className 的小驼峰写法
         */
        @Component(value = "userService")
        public class UserService {
            public void add() {
                System.out.println("UserService......");
            }
        }
        

        image-20220307180922071

      • 经过三个步骤我们便通过注解为类创建了对象,接下来我们测试一下

        package com.atguigu.spring5.testdemo;
        
        import com.atguigu.spring5.service.UserService;
        import org.junit.Test;
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        
        /**
         * @author workplace
         * @date 2022/3/7 17:40
         */
        public class SpringDemoTest {
            @Test
            public void testUserService() {
                ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
                UserService userService = context.getBean("userService", UserService.class);
                System.out.println(userService);
                userService.add();
            }
        }
        

        image-20220307181356730

        结果

        com.atguigu.spring5.service.UserService@b62fe6d
        UserService......
        

        image-20220307181426491

      • 总结:这是大致的流程

        image-20220307180533772

        我们首先引入依赖,开启组件扫描,通过注解给类创建对象。就可以通过注解来创建bean了。

    3. 开启组件扫描的细节

      1. 示例一

        <!-- 示例一
            use-default-filters="false" 表示现在不使用默认 filters,自己配置 filters
            context:include-filter 设置哪些内容需要扫描
            这一段的意思是:我 package 除了 context:include-filter 之外什么都不扫描。
        -->
        <context:component-scan base-package="com.atguigu" use-default-filters="false">
            <context:include-filter type="annotation"
                                    expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        

        在开启扫描的时候可以添加属性 (use-default-filters),用来选择是否使用默认扫描。

        (use-default-filters)true 表示使用默认扫描,扫描 package 下的全部类看是否有注解生成 bean。

        (use-default-filters)false 表示不使用默认扫描,通过 <context:include-filter></context:include-filter> 标签设置哪些内容需要扫描

      2. 实例二

        <!-- 实例二
             现在使用默认 filters,扫描下面 package 的全部类
             context:exclude-filter 设置哪些内容不需要扫描
             这一段的意思就是:我 package 里的除了 context:exclude-filter 之外其他的都扫描。
        -->
        <context:component-scan base-package="com.atguigu">
            <context:exclude-filter type="annotation"
                                    expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        

        这里没有设置 (use-default-filters) 所以选择了默认扫描。

        通过 <context:exclude-filter></context:exclude-filter> 标签设置哪些内容不需要扫描。

    4. Spring针对Bean管理中属性注入提供了三个注解

      1. @Autowired:根据属性类型进行自动装配(针对对象类型)

      2. @Qualifier:根据属性名称进行自动注入(针对对象类型)

      3. @Resource:可以根据类型注入,可以根据名称注入(针对对象类型)

      4. @Value:注入普通类型属性(针对普通类型)

    5. 基于注解方式实行属性注入

      1. @Autowired 作为示范

        • 通过三个类之间的交流,实现自动装配。

          UserDao 类

          package com.atguigu.spring5.dao;
          
          /**
           * @author workplace
           * @date 2022/3/7 21:20
           */
          public interface UserDao {
              /**
               *
               */
              void say();
          }
          

          UserDaoImpl 类

          package com.atguigu.spring5.dao;
          
          import org.springframework.stereotype.Repository;
          
          /**
           * @author workplace
           * @date 2022/3/8 15:21
           */
          @Repository
          public class UserDaoImpl implements UserDao{
              @Override
              public void say() {
                  System.out.println("UserDaoImpl ......");
              }
          }
          

          UserService 类:展示了通过注解实现 bean 的自动装配。可以看出这种方法是不需要用到 set 方法。

          package com.atguigu.spring5.service;
          
          import com.atguigu.spring5.dao.UserDao;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;
          
          @Service(value = "userService")
          public class UserService {
          
              /**
               * 展示了通过注解实现 bean 的自动装配。
               * 创建 dao 类属性
               * 不需要添加 set 方法。
               * 注解里面包含了添加、注入的操作
               */
              @Autowired
              private UserDao userDao;
          
              public void add() {
                  // 测试 @Autowired 标签是否将类自动注入
                  userDao.say();
                  System.out.println("UserService......");
              }
          }
          

          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:context="http://www.springframework.org/schema/context"
                 xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
          
              <context:component-scan base-package="com.atguigu.spring5"/>
          
          </beans>
          

          测试类

          package com.atguigu.spring5.testdemo;
          
          import com.atguigu.spring5.service.UserService;
          import org.junit.Test;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          /**
           * @author workplace
           * @date 2022/3/7 17:40
           */
          public class SpringDemoTest {
              @Test
              public void testUserService() {
                  ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
                  UserService userService = context.getBean("userService", UserService.class);
                  System.out.println(userService);
                  userService.add();
              }
          }
          

          结果:

          com.atguigu.spring5.service.UserService@22635ba0
          UserDaoImpl ......
          UserService......
          

          image-20220308154046829

          可以看到通过注解创建对象全部成功,并且通过注解实现了 bean 的自动装配。

          image-20220308155617887

      2. @Qualifier 作为示范

        • 整体使用和 @Autowired 类似。区别在于它是根据属性名称进行自动注入,都是配合 @Autowired 一起使用。接下来我们继续用上面的例子稍做修改进行演示

          UserDao 类

          package com.atguigu.spring5.dao;
          
          /**
           * @author workplace
           * @date 2022/3/7 21:20
           */
          public interface UserDao {
              /**
               *
               */
              void say();
          }
          

          UserDaoImpl 类

          package com.atguigu.spring5.dao;
          
          import org.springframework.stereotype.Repository;
          
          /**
           * @author workplace
           * @date 2022/3/8 15:21
           */
          @Repository(value = "userDaoImpl")
          public class UserDaoImpl implements UserDao{
              @Override
              public void say() {
                  System.out.println("UserDaoImpl ......");
              }
          }
          

          UserService 类:展示了通过注解实现 bean 的自动装配。可以看出这种方法是不需要用到 set 方法。

          package com.atguigu.spring5.service;
          
          import com.atguigu.spring5.dao.UserDao;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.beans.factory.annotation.Qualifier;
          import org.springframework.stereotype.Service;
          
          @Service(value = "userService")
          public class UserService {
          
              /**
               * 创建 dao 类属性
               * 不需要添加 set 方法。
               * 注解里面包含了添加、注入的操作
               */
              @Autowired
              @Qualifier(value = "userDaoImpl")
              private UserDao userDao;
          
              public void add() {
                  // 测试 @Autowired 标签是否将类自动注入
                  userDao.say();
                  System.out.println("UserService......");
              }
          }
          

          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:context="http://www.springframework.org/schema/context"
                 xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          
          
              <context:component-scan base-package="com.atguigu.spring5"/>
          
          </beans>
          

          测试类

          package com.atguigu.spring5.testdemo;
          
          import com.atguigu.spring5.service.UserService;
          import org.junit.Test;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          /**
           * @author workplace
           * @date 2022/3/7 17:40
           */
          public class SpringDemoTest {
              @Test
              public void testUserService() {
                  ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
                  UserService userService = context.getBean("userService", UserService.class);
                  System.out.println(userService);
                  userService.add();
              }
          }
          

          结果

          com.atguigu.spring5.service.UserService@23f7d05d
          UserDaoImpl ......
          UserService......
          

          image-20220308160752785

          可以看到这里是通过获取 bean 的名称来进行装配

          image-20220308161159660

      3. @Value 作为示范

        • 这个注解常用于普通类型属性上。就是 @Value(value = "符合类型的值") 这样子就可以为普通类型进行属性注入。

          UserService 类

          package com.atguigu.spring5.service;
          
          import org.springframework.beans.factory.annotation.Value;
          import org.springframework.stereotype.Service;
          
          @Service
          public class UserService {
          
              @Value(value = "1234")
              private String str;
          
              @Value(value = "123")
              private int num;
          
              public void add() {
                  System.out.println(str);
                  System.out.println(num);
              }
          }
          

          SpringDemoTest 测试类

          package com.atguigu.spring5.testdemo;
          
          import com.atguigu.spring5.service.UserService;
          import org.junit.Test;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;
          
          /**
           * @author workplace
           * @date 2022/3/7 17:40
           */
          public class SpringDemoTest {
              @Test
              public void testUserService() {
                  ApplicationContext context
                          = new ClassPathXmlApplicationContext("bean1.xml");
                  UserService userService = context.getBean("userService", UserService.class);
                  System.out.println(userService);
                  userService.add();
              }
          }
          

          结果

          1234
          123