Spring XML三种实例化Bean的方式

  • 使用类构造器实例化(默认无参数)
  • 使用静态工厂方法实例化(简单工厂模式)
  • 使用实例工厂方法实例化(工厂方法模式)

第一种:使用类构造器实例化(默认无参数)

  • 创建Bean类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.example.bean.demo;

    /**
    * Bean的实例化的三种方式:采用无参数的构造方法的方式
    *
    * @author jinglv
    * @date 2020/12/27
    */
    public class Bean1 {
    /**
    * 无参构造方法
    */
    public Bean1() {
    System.out.println("Bean1被实例化了...");
    }
    }
  • 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?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 id="bean1" class="com.example.bean.demo.Bean1"/>

    </beans>
  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.example.bean.demo;

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

    /**
    * Bean的实例化的三种方式:采用无参数的构造方法的方式测试
    *
    * @author jinglv
    * @date 2020/12/27
    */
    class Bean1Test {
    @Test
    void testBean1() {
    // 创建工厂
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 通过工厂获得类的实例
    Bean1 bean1 = (Bean1) context.getBean("bean1");
    }
    }
  • 执行结果

    image-20210402114300828

第二种:使用静态工厂方法实例化(简单工厂模式)

  • 创建Bean类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package com.example.bean.demo;

    /**
    * Bean的实例化的三种方式:静态工厂实例化方式
    *
    * @author jinglv
    * @date 2020/12/27
    */
    public class Bean2 {
    }
  • 对应Bean创建工厂类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.example.bean.demo.factory;

    import com.example.bean.demo.Bean2;

    /**
    * Bean2的静态工厂(提供一个静态方法返回Bean2)
    *
    * @author jinglv
    * @date 2020/12/27
    */
    public class Bean2Factory {
    public static Bean2 createBean2() {
    System.out.println("Bean2Factory已执行...");
    return new Bean2();
    }
    }
  • 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?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 id="bean1" class="com.example.bean.demo.Bean1"/>

    <!--第二种:静态工厂的方式-->
    <bean id="bean2" class="com.example.bean.demo.factory.Bean2Factory" factory-method="createBean2"/>

    </beans>
  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.example.bean.demo;

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

    /**
    * Bean的实例化的三种方式:静态工厂方式测试
    *
    * @author jinglv
    * @date 2020/12/27
    */
    class Bean2Test {
    @Test
    void testBean1() {
    // 创建工厂
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 通过工厂获得类的实例
    Bean2 bean2 = (Bean2) context.getBean("bean2");
    }
    }
  • 执行结果

    image-20210402114456423

第三种:使用实例工厂方法实例化(工厂方法模式)

  • 创建Bean类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.example.bean.demo;

    /**
    * Bean的实例化的三种方式:实例工厂实例化
    *
    * @author jinglv
    * @date 2020/12/27
    */
    public class Bean3 {
    }

  • 对应Bean创建工厂类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package com.example.bean.demo.factory;

    import com.example.bean.demo.Bean3;

    /**
    * Bean3的实例工厂(提供一个非静态方法返回Bean3)
    *
    * @author jinglv
    * @date 2020/12/27
    */
    public class Bean3Factory {
    public Bean3 createBean3() {
    System.out.println("Bean3Factory已执行...");
    return new Bean3();
    }
    }
  • 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <?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 id="bean1" class="com.example.bean.demo.Bean1"/>

    <!--第二种:静态工厂的方式-->
    <bean id="bean2" class="com.example.bean.demo.factory.Bean2Factory" factory-method="createBean2"/>

    <!--第三章:实例工厂的方式(非静态)-->
    <bean id="bean3Factory" class="com.example.bean.demo.factory.Bean3Factory"/>
    <bean id="bean3" factory-bean="bean3Factory" factory-method="createBean3"/>

    </beans>
  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    package com.example.bean.demo;

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

    /**
    * Bean的实例化的三种方式:实例工厂方式测试
    *
    * @author jinglv
    * @date 2020/12/27
    */
    class Bean3Test {
    @Test
    void testBean3() {
    // 创建工厂
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 通过工厂获得类的实例
    Bean3 bean3 = (Bean3) context.getBean("bean3");
    }
    }
  • 执行结果

    image-20210402114740442

Spring的Bean管理–XML方式之配置

Bean的配置

  • id和name

    • 一般情况下,装配一个Bean时,通过指定一个id属性作为Bean的名称
    • id属性在IOC容器中必须是唯一的
    • 如果Bean的名称中含有特殊字符,就需要使用name属性
  • class

    • class用于设置一个类的完全路径名称,主要作用是IOC容器生成类的实例
  • scope

    • 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton
  • constructor-arg

    • <bean>元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型
  • property

    • <bean>元素的子元素,用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名
  • ref

    • <property> <constructor-arg> 等元素的子元索,该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用
  • value

    • <property><constractor-arg> 等元素的子元素,用于直接指定一个常量值
  • list

    • 用于封装 List 或数组类型的依赖注入
  • set

    • 用于封装 Set 类型属性的依赖注入
  • map

    • 用于封装 Map 类型属性的依赖注入
  • entry

    • 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值

Bean的作用域(Scope)

类别 说明
singleton 在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存放
prototype 每次调用getBean()时都会返回一个新的实例
request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session 同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean。该作用域仅适用于WebApplicationContext环境
  • 编写实体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.example.bean.demo.scope;

    /**
    * Bean的作用范围
    *
    * @author jinglv
    * @date 2020/12/27
    */
    public class Person {

    }
  • 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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="singleton" 单例,默认的(如果不配置该参数则默认是单例)
    scope="prototype" 每次调用getBean()时都会返回一个新的实例

    -->
    <bean id="person" class="com.example.bean.demo.scope.Person" scope="singleton"/>


    </beans>
  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.example.bean.demo.scope;

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

    /**
    * Bean的作用范围的测试
    *
    * @author jinglv
    * @date 2020/12/27
    */
    class PersonTest {

    @Test
    void test1() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-scope.xml");
    Person person1 = (Person) context.getBean("person");
    Person person2 = (Person) context.getBean("person");
    System.out.println(person1);
    System.out.println(person2);
    }
    }

    注意:查看比较输出的内存地址

  • 执行结果

    • singleton:内存地址是一样的

      image-20210402115316710

    • prototype:内存地址每次运行都不一样

      image-20210402115334525

Bean的生命周期

Spring初始化bean或销毁bean时,有时需要做一些处理工作,因此spring可以在创建和销毁bean的时候调用bean的两个生命周期的方法

1
<bean id="xxx" calss="xxxx.xxxx.xxx" init-method="init" destory-method="destory"/>
  • 当bean被载入到容器的时候调用init
  • 当bean从容器中删除的时候调用destory(scope=singleton有效,多例时不知道需要销毁哪个则无效)

生命周期的完整过程

![image-20210402115510137](../../../../../../Library/Application Support/typora-user-images/image-20210402115510137.png)

  1. nstantiate bean对象实例化
  2. populate properties 封装属性
  3. 如果Bean实现BeanNameAware执行setBeanName
  4. 如果Bean实现BeanFactoryAware或者ApplicationContextAware设置工厂setBeanFactory或者上下文对象setApplicationContext
  5. 如果存在类实现BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization
  6. 如果Bean实现InitializingBean执行afterPropertiesSet
  7. 调用<bean init-method="init">指定初始化方法init
  8. 如果存在类实现BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
  9. 执行业务处理
  10. 如果Bean实现DisposableBean执行destroy
  11. 调用<bean destroy-method="customerDestory">指定销毁方法customerDestory
  • 编写实体代码

    • Man.java

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      package com.example.bean.demo.lifecycle;

      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.BeanNameAware;
      import org.springframework.beans.factory.DisposableBean;
      import org.springframework.beans.factory.InitializingBean;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.ApplicationContextAware;

      /**
      * Bean的生命周期
      *
      * @author jingLv
      * @date 2020-04-26 11:12 AM
      */
      public class Man implements BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {

      private String name;

      public void setName(String name) {
      System.out.println("第二步:设置属性...");
      this.name = name;
      }

      public Man() {
      System.out.println("第一步:MAN被实例化了...");
      }

      public void setUp() {
      System.out.println("第七步:MAN被初始化了...");
      }

      public void tearDown() {
      System.out.println("第十一步:MAN被销毁了...");
      }

      @Override
      public void setBeanName(String s) {
      System.out.println("第三步:设置Bean的名称(<bean>的id)...");
      }

      @Override
      public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
      System.out.println("第四步:了解工厂的信息...");
      }

      @Override
      public void afterPropertiesSet() throws Exception {
      System.out.println("第六步:属性设置后...");
      }

      public void run() {
      System.out.println("第九步:执行业务方法...");
      }

      @Override
      public void destroy() throws Exception {
      System.out.println("第十步:执行Spring销毁的方法...");
      }
      }
    • MyBeanPostProcessor.java

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      package com.example.bean.demo.lifecycle;

      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanPostProcessor;

      /**
      * @author jingLv
      * @date 2020-04-26 11:48 AM
      */
      public class MyBeanPostProcessor implements BeanPostProcessor {

      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("第五步:初始化前方法...");
      return bean;
      }

      /**
      * 对 postProcessAfterInitialization 初始化后方法进行增强。
      *
      * @param bean
      * @param beanName
      * @return
      * @throws BeansException
      */
      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("第八步:初始化后方法...");
      return bean;
      }
      }

  • 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?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 id="man" class="com.example.bean.demo.lifecycle.Man" init-method="setUp" destroy-method="tearDown">
    <property name="name" value="Life"/>
    </bean>

    <bean class="com.example.bean.demo.lifecycle.MyBeanPostProcessor"/>

    </beans>
  • 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.example.bean.demo.lifecycle;

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

    /**
    * @author jinglv
    * @date 2020/12/27
    */
    class ManTest {

    @Test
    void test() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
    Man man = (Man) context.getBean("man");
    man.run();
    context.close();
    }

    }
  • 执行结果

    image-20210402115920857

beanpostprocessor的作用

beanpostprocessor类可以在生成类的过程当中,对类产生代理,并可以对类中的方法进行增强。为后面学习AOP打下基础。

  1. 新建接口,并演示几个方法,实现接口的实现类

    • UserDao.java

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      package com.example.bean.demo.lifecycle.dao;

      /**
      * @author jingLv
      * @date 2020-04-26 12:57 PM
      */
      public interface UserDao {

      /**
      * 查询所有用户
      */
      void findAll();

      /**
      * 保存用户
      */
      void save();

      /**
      * 更新用户
      */
      void update();

      /**
      * 删除用户
      */
      void delete();

      }

  • UserDaoImpl.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.example.bean.demo.lifecycle.dao;

    /**
    * @author jingLv
    * @date 2020-04-26 12:59 PM
    */
    public class UserDaoImpl implements UserDao {
    @Override
    public void findAll() {
    System.out.println("查询所有用户");
    }

    @Override
    public void save() {
    System.out.println("保存用户...");
    }

    @Override
    public void update() {
    System.out.println("更新用户...");
    }

    @Override
    public void delete() {
    System.out.println("删除用户...");
    }
    }
  1. 编写增强代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    package com.example.bean.demo.lifecycle;

    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;

    /**
    * @author jingLv
    * @date 2020-04-26 11:48 AM
    */
    public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("第五步:初始化前方法...");
    return bean;
    }

    /**
    * 对 postProcessAfterInitialization 初始化后方法进行增强。
    *
    * @param bean
    * @param beanName
    * @return
    * @throws BeansException
    */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("第八步:初始化后方法...");
    //使用代理,构造匿名函数
    if ("userDao".equals(beanName)) {
    Object proxy = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // save方法之前进行增强
    if ("save".equals(method.getName())) {
    System.out.println("权限校验==========");
    // 传入属性
    return method.invoke(bean, args);
    }
    return method.invoke(bean, args);
    }
    });
    return proxy;
    } else {
    return bean;
    }
    }
    }

  1. 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?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.example.bean.demo.lifecycle.MyBeanPostProcessor"/>

    <bean id="userDao" class="com.example.bean.demo.lifecycle.dao.UserDaoImpl"/>

    </beans>
  1. 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.example.bean.demo.lifecycle.dao;

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

    /**
    * @author jinglv
    * @date 2020/12/28
    */
    class UserDaoTest {

    @Test
    void test() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-beanpostprocessor.xml");
    UserDao userDao = (UserDao) context.getBean("userDao");

    userDao.findAll();
    userDao.save();
    userDao.update();
    userDao.delete();
    }

    }
  1. 执行结果

    image-20210402120409610

Spring的Bean管理–XML方式之属性注入

属性注入方式及构造方法的属性注入

  • 对于类成员变量,注入方式有三种
    • 构造函数注入
    • 属性setter方法注入
    • 接口注入(Spring不支持)

构造方法注入

  • 通过构造方法注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用
  • 构造器注入在<constructor-arg>元素里声明的属性
  1. 新建类对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package com.example.bean.demo.di;

    /**
    * @author jinglv
    * @date 2021/01/12
    */
    public class User {
    private String name;
    private Integer age;

    public User(String name, Integer age) {
    this.name = name;
    this.age = age;
    }

    @Override
    public String toString() {
    return "User{" +
    "name='" + name + '\'' +
    ", age=" + age +
    '}';
    }
    }
  1. 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <?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 id="user" class="com.example.bean.demo.di.User">
    <constructor-arg name="name" value="xiaohong"/>
    <constructor-arg name="age" value="20"/>
    </bean>


    </beans>
  1. 编写测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.example.bean.demo.di;

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

    /**
    * @author jinglv
    * @date 2021/01/12
    */
    class UserTest {

    @Test
    void testUser() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-di.xml");
    User user = (User) context.getBean("user");
    System.out.println(user);
    }

    }
  1. 执行结果

    image-20210402125616767

set方法注入

  • 使用set方法注入,在spring配置文件中,通过<property>设置注入的属性
  1. 新建类对象Person和Cat

    • Person.java

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      package com.example.bean.demo.di;

      /**
      * @author jinglv
      * @date 2021/01/12
      */
      public class Person {
      private String name;
      private Integer age;
      private Cat cat;

      public String getName() {
      return name;
      }

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

      public Integer getAge() {
      return age;
      }

      public void setAge(Integer age) {
      this.age = age;
      }

      public Cat getCat() {
      return cat;
      }

      public void setCat(Cat cat) {
      this.cat = cat;
      }

      @Override
      public String toString() {
      return "Person{" +
      "name='" + name + '\'' +
      ", age=" + age +
      ", cat=" + cat +
      '}';
      }
      }
  • Cat.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.example.bean.demo.di;

    /**
    * @author jinglv
    * @date 2021/01/12
    */
    public class Cat {
    private String name;

    public String getName() {
    return name;
    }

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

    @Override
    public String toString() {
    return "Cat{" +
    "name='" + name + '\'' +
    '}';
    }
    }
  1. 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?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 set方法的属性注入-->
    <bean id="person" class="com.example.bean.demo.di.Person">
    <!--普通类型value-->
    <property name="name" value="xiaohei"/>
    <property name="age" value="22"/>
    <!--对象类型ref,ref引入其他bean的id或name-->
    <property name="cat" ref="cat"/>
    </bean>

    <bean id="cat" class="com.example.bean.demo.di.Cat">
    <property name="name" value="ketty"/>
    </bean>

    </beans>
  1. 编写测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.example.bean.demo.di;

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

    /**
    * @author jinglv
    * @date 2021/01/12
    */
    class PersonTest {

    @Test
    void testPerson() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-di.xml");
    Person person = (Person) context.getBean("person");
    System.out.println(person);
    }

    }
  1. 执行结果

    image-20210402125935537

p名称空间

  • 使用p命名空间
  • 为了简化XML文件配置,Spring从2.5开始引入一个新的p名称空间
  • p:<属性名>=”xxx”引入常量
  • p:<属性名>-ref=”xxx”引用其它Bean对象

已上面set方法注入的示例为例,修改为p命名空间,配置文件修改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!--Bean的p名称空间的属性注入-->
<bean id="person-p" class="com.example.bean.demo.di.Person" p:name="芙蓉姐姐" p:age="48" p:cat-ref="cat-p">
</bean>

<bean id="cat-p" class="com.example.bean.demo.di.Cat" p:name="Mimi"/>

</beans>

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.example.bean.demo.p;

import com.example.bean.demo.di.Person;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
* @author jinglv
* @date 2021/01/17
*/
public class PersonTest {

@Test
void testPerson() {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-p.xml");
Person person = (Person) context.getBean("person");
System.out.println(person);
}
}

执行结果如下:

image-20210402131027419

SpEL注入

  • SpEL:spring expression language, spring表达式语言,对依赖注入进行简化

  • 语法:#{表达式}

  • 示例:<bean id="" value="#{表达式}">

    1
    2
    3
    4
    5
    6
    SpEL表达式语言
    语法:#{}
    #{'hello'}:使用字符串
    #{beanId}:使用另一个bean
    #{beanId.content.toUpperCase()}:使用指定名属性,并使用方法
    #{T(java.lang.Math).PI}:使用静态字段或方法
  1. 创建实体类

    • Product.java

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      package com.example.bean.demo.spel;

      /**
      * @author jinglv
      * @date 2021/01/17
      */
      public class Product {
      private String name;
      private Double price;
      private Category category;

      public String getName() {
      return name;
      }

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

      public Double getPrice() {
      return price;
      }

      public void setPrice(Double price) {
      this.price = price;
      }

      public Category getCategory() {
      return category;
      }

      public void setCategory(Category category) {
      this.category = category;
      }

      @Override
      public String toString() {
      return "Product{" +
      "name='" + name + '\'' +
      ", price=" + price +
      ", category=" + category +
      '}';
      }
      }
  • ProductInfo.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package com.example.bean.demo.spel;

    /**
    * @author jinglv
    * @date 2021/01/17
    */
    public class ProductInfo {
    public Double calculatePrice() {
    return Math.random() * 199;
    }
    }
  • Category.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.example.bean.demo.spel;

    /**
    * @author jinglv
    * @date 2021/01/17
    */
    public class Category {
    private String name;

    public String getName() {
    return name;
    }

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

    @Override
    public String toString() {
    return "Category{" +
    "name='" + name + '\'' +
    '}';
    }
    }
  1. 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <?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的SpEL的属性注入-->
    <bean id="product" class="com.example.bean.demo.spel.Product">
    <property name="name" value="#{'男装'}"/>
    <property name="price" value="#{productInfo.calculatePrice()}"/>
    <property name="category" value="#{category}"/>
    </bean>

    <bean id="category" class="com.example.bean.demo.spel.Category">
    <property name="name" value="#{'服装'}"/>
    </bean>

    <bean id="productInfo" class="com.example.bean.demo.spel.ProductInfo"/>


    </beans>
  1. 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.example.bean.demo.spel;

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

    /**
    * @author jinglv
    * @date 2021/01/17
    */
    class ProductTest {

    @Test
    void test() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-spel.xml");
    Product product = (Product) context.getBean("product");
    System.out.println(product);
    }

    }
  1. 执行结果

    image-20210402131356145

复杂类型的属性注入

  • 数组类型的属性注入
  • List集合类型的属性注入
  • Set集合类型的属性注入
  • Map集合类型的属性注入
  • Properties类型的属性注入
  1. 创建类型对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    package com.example.bean.demo.type;

    import java.util.*;

    /**
    * @author jinglv
    * @date 2021/01/17
    */
    public class CollectionBean {
    /**
    * 数组类型
    */
    private String[] arrs;
    /**
    * list集合类型
    */
    private List<String> list;
    /**
    * set集合类型
    */
    private Set<String> set;
    /**
    * map集合类型
    */
    private Map<String, Integer> map;
    /**
    * 属性类型
    */
    private Properties properties;

    public String[] getArrs() {
    return arrs;
    }

    public void setArrs(String[] arrs) {
    this.arrs = arrs;
    }

    public List<String> getList() {
    return list;
    }

    public void setList(List<String> list) {
    this.list = list;
    }

    public Set<String> getSet() {
    return set;
    }

    public void setSet(Set<String> set) {
    this.set = set;
    }

    public Map<String, Integer> getMap() {
    return map;
    }

    public void setMap(Map<String, Integer> map) {
    this.map = map;
    }

    public Properties getProperties() {
    return properties;
    }

    public void setProperties(Properties properties) {
    this.properties = properties;
    }

    @Override
    public String toString() {
    return "CollectionBean{" +
    "arrs=" + Arrays.toString(arrs) +
    ", list=" + list +
    ", set=" + set +
    ", map=" + map +
    ", properties=" + properties +
    '}';
    }
    }
  1. 编写配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    <?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="collectionBean" class="com.example.bean.demo.type.CollectionBean">
    <!--数组类型-->
    <property name="arrs">
    <list>
    <value>aaa</value>
    <value>bbb</value>
    <value>ccc</value>
    </list>
    </property>
    <!--list集合的类型-->
    <property name="list">
    <list>
    <value>one</value>
    <value>two</value>
    <value>three</value>
    </list>
    </property>
    <!--set集合的类型-->
    <property name="set">
    <set>
    <value>zzz</value>
    <value>xxx</value>
    <value>ccc</value>
    </set>
    </property>
    <!--map集合的类型-->
    <property name="map">
    <map>
    <entry key="one" value="111"/>
    <entry key="two" value="222"/>
    <entry key="three" value="333"/>
    </map>
    </property>
    <!--Properties属性-->
    <property name="properties">
    <props>
    <prop key="username">root</prop>
    <prop key="password">123123</prop>
    </props>
    </property>
    </bean>

    </beans>
  1. 测试代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package com.example.bean.demo.type;

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

    /**
    * @author jinglv
    * @date 2021/01/17
    */
    class CollectionBeanTest {

    @Test
    void test() {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-type.xml");
    CollectionBean collectionBean = (CollectionBean) context.getBean("collectionBean");
    System.out.println(collectionBean);
    }
    }
  1. 执行结果

    1
    CollectionBean{arrs=[aaa, bbb, ccc], list=[one, two, three], set=[zzz, xxx, ccc], map={one=111, two=222, three=333}, properties={password=123123, username=root}}