Spring-1-透彻理解Spring XML的Bean创建--IOC

学习目标

上一篇文章我们介绍了什么是Spring,以及Spring的一些核心概念,并且快速快发一个Spring项目,实现IOC和DI,今天具体来讲解IOC

能够说出IOC的基础配置和Bean作用域

了解Bean的生命周期

能够说出Bean的实例化方式

一、Bean的基础配置

问题导入

问题1:在标签上如何配置别名?

问题2:Bean的默认作用范围是什么?如何修改?

1 Bean基础配置【重点】

配置说明

Spring-1-透彻理解Spring XML的Bean创建--IOC_第1张图片

2 Bean别名配置

配置说明

Spring-1-透彻理解Spring XML的Bean创建--IOC_第2张图片

注意事项:

获取bean无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionException
NoSuchBeanDefinitionException: No bean named 'studentDaoImpl' available

代码演示

【第0步】创建项目名称为10_2_IOC_Bean的maven项目

【第一步】导入Spring坐标

  
      
      
          org.springframework
          spring-context
          5.3.15
      

      
      
          org.junit.jupiter
          junit-jupiter
          5.8.2
          test
      

      
          org.projectlombok
          lombok
          1.18.28
      
  

【第二步】导入Student实体类

@Data
@ToString
@AllArgsConstructor
public class Student {
    private String name;
    private String address;
    private Integer age;

    private Integer status;
}

【第三步】定义Spring管理的类(接口)

  • StudentDao接口和StudentDaoImpl实现类

package com.zbbmeta.dao;

public interface StudentDao {
    /**
     * 添加学生
     */
    void save();
}
package com.zbbmeta.dao.impl;

import com.zbbmeta.dao.StudentDao;

public class StudentDaoImpl implements StudentDao {
    @Override
    public void save() {
        System.out.println("DAO: 添加学生信息到数据库...");
    }
}

  • StudentService接口和StudentServiceImpl实现类

package com.zbbmeta.service;

public interface StudentService {
    /**
     * 添加学生
     */
    void save();
}

package com.zbbmeta.service.impl;

import com.zbbmeta.dao.StudentDao;
import com.zbbmeta.dao.impl.StudentDaoImpl;
import com.zbbmeta.service.StudentService;

public class StudentServiceImpl implements StudentService {

    //创建成员对象
    private StudentDao studentDao = new StudentDaoImpl();
    @Override
    public void save() {

    }
}

【第四步】创建Spring配置文件在resources目录下,配置对应类作为Spring管理的bean对象

  • 定义application.xml配置文件并配置StudentDaoImpl



    
    
    


注意事项:bean定义时id属性和name中名称不能有重复的在同一个上下文中(IOC容器中)不能重复

【第四步】根据容器别名获取Bean对象

package com.zbbmeta;

import com.zbbmeta.dao.StudentDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class NameApplication {
    public static void main(String[] args) {
        /**
         * 从IOC容器里面根据别名获取对象执行
         */
        //1.根据配置文件application.xml创建IOC容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        //2.从IOC容器里面获取id="abc"对象
        StudentDao studentDao = (StudentDao) ac.getBean("abc");
        //3.执行对象方法
        studentDao.save();
        //4.关闭容器
        ac.close();
    }
}

打印结果

Spring-1-透彻理解Spring XML的Bean创建--IOC_第3张图片

3 Bean作用范围配置【重点】

配置说明

Spring-1-透彻理解Spring XML的Bean创建--IOC_第4张图片

扩展: scope的取值不仅仅只有singleton和prototype,还有request、session、application、 websocket ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中。

代码演示

在application.xml中配置prototype格式

  • 定义application.xml配置文件并配置StudentDaoImpl



    
    
    


根据容器别名获取Bean对象

package com.zbbmeta;

import com.zbbmeta.dao.StudentDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ScopeApplication {
    public static void main(String[] args) {
        /**
         * Bean的作用域范围演示
         */
        //1.根据配置文件application.xml创建IOC容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        //2.从IOC容器里面获取id="studentService"对象
        System.out.println("=========singleton(单例)模式=========");
        StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
        StudentDao studentDao1 = (StudentDao) ac.getBean("studentDao");
        System.out.println("studentDao = " + studentDao);
        System.out.println("studentDao1 = " + studentDao1);
        System.out.println("=========prototype模式=========");
        StudentDao studentDao2 = (StudentDao) ac.getBean("studentDao4");
        StudentDao studentDao3 = (StudentDao) ac.getBean("studentDao4");
        System.out.println("studentDao2 = " + studentDao2);
        System.out.println("studentDao3 = " + studentDao3);
        //4.关闭容器
        ac.close();
    }
}

打印结果

Spring-1-透彻理解Spring XML的Bean创建--IOC_第5张图片

注意:在我们的实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性

二、Bean的实例化

思考:Bean的实例化方式有几种?

2 实例化Bean的三种方式

2.1 构造方法方式【重点】

  • BookDaoImpl实现类

public class StudentDaoImpl implements StudentDao {
    public StudentDaoImpl() {
        System.out.println("Student dao constructor is running ....");
    }

    @Override
    public void save() {
        System.out.println("DAO: 添加学生信息到数据库...");
    }
}
  • application.xml配置

    
    
    
  • AppForInstanceBook测试类

public class OneApplication {
    public static void main(String[] args) {
        /**
         * 无参构造方式创建Bean
         */
        //1.根据配置文件application.xml创建IOC容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        //2.从IOC容器里面获取id="studentService"对象
        StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
        //3.执行对象方法
        studentDao.save();
        //4.关闭容器
        ac.close();
    }
}
  • 运行结果

Spring-1-透彻理解Spring XML的Bean创建--IOC_第6张图片

注意:无参构造方法如果不存在,将抛出异常BeanCreationException

2.2 静态工厂方式

  • StudentDaoFactory工厂类

package com.zbbmeta.factory;

import com.zbbmeta.dao.StudentDao;
import com.zbbmeta.dao.impl.StudentDaoImpl;

public class StudentDaoFactory {
//    静态工厂创建对象
    public static StudentDao getStudentDao(){
        System.out.println("Student static factory setup....");
        return new StudentDaoImpl();
    }
}
  • applicationContext.xml配置




    
    


    
    




注意:测试前最好把之前使用Bean标签创建的对象进行注释

  • TwoApplication测试类

public class TwoApplication {
    public static void main(String[] args) {
        /**
         * 无参构造方式创建Bean
         */
        //1.根据配置文件application.xml创建IOC容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        //2.从IOC容器里面获取id="studentService"对象
        StudentDao studentDao = (StudentDao) ac.getBean("studentDao2");
        //3.执行对象方法
        studentDao.save();
        //4.关闭容器
        ac.close();
    }
}
  • 运行结果

Spring-1-透彻理解Spring XML的Bean创建--IOC_第7张图片

2.3 实例工厂方式

  • UserDao接口和UserDaoImpl实现类

    //利用实例方法创建StudentDao对象
    public StudentDao getStudentDao2(){
        System.out.println("调用了实例工厂方法");
        return new StudentDaoImpl();
    }
  • StudentDaoFactory工厂类添加方法

//实例工厂创建对象
public class UserDaoFactory {
    public UserDao getUserDao(){
        return new UserDaoImpl();
    }
}
  • applicationContext.xml配置




    
    


    



    
    
    
    
    



  • ThreeApplication测试类

package com.zbbmeta;

import com.zbbmeta.dao.StudentDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ThreeApplication {
    public static void main(String[] args) {
        /**
         * 无参构造方式创建Bean
         */
        //1.根据配置文件application.xml创建IOC容器
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        //2.从IOC容器里面获取id="studentService"对象
        StudentDao studentDao = (StudentDao) ac.getBean("studentDao3");
        //3.执行对象方法
        studentDao.save();
        //4.关闭容器
        ac.close();
    }
}

  • 运行结果

Spring-1-透彻理解Spring XML的Bean创建--IOC_第8张图片

三、Bean的生命周期【了解】

问题导入

问题1:多例的Bean能够配置并执行销毁的方法?

问题2:如何做才执行Bean销毁的方法?

1 生命周期相关概念介绍

  • 生命周期:从创建到消亡的完整过程

  • bean生命周期:bean从创建到销毁的整体过程

  • bean生命周期控制:在bean创建后到销毁前做一些事情

1.1生命周期过程

  • 初始化容器
    • 创建对象(内存分配)

    • 执行构造方法

    • 执行属性注入(set操作)

    • 执行bean初始化方法

  • 使用bean
    • 执行业务操作

  • 关闭/销毁容器
    • 执行bean销毁方法

2 代码演示

2.1 Bean生命周期控制

【第0步】创建项目名称为10_4_IOC_BeanLifeCycle的maven项目

【第一步】导入Spring坐标

  
      
      
          org.springframework
          spring-context
          5.3.15
      

      
      
          org.junit.jupiter
          junit-jupiter
          5.8.2
          test
      

      
          org.projectlombok
          lombok
          1.18.28
      
  

【第二步】导入Student实体类

@Data
@ToString
@AllArgsConstructor
public class Student {
    private String name;
    private String address;
    private Integer age;

    private Integer status;
}

【第三步】定义Spring管理的类(接口)

  • StudentDao接口和StudentDaoImpl实现类

package com.zbbmeta.dao;

public interface StudentDao {
    /**
     * 添加学生
     */
    void save();
}
package com.zbbmeta.dao.impl;

import com.zbbmeta.dao.StudentDao;

public class StudentDaoImpl implements StudentDao {

    public StudentDaoImpl(){
        System.out.println("Student Dao 的无参构造");
    }

    @Override
    public void save() {
        System.out.println("DAO: 添加学生信息到数据库...");
    }

    public void init(){
        System.out.println("Student Dao 的初始化方法");
    }

    public void destroy(){
        System.out.println("Student Dao 的销毁方法");
    }
}

【第四步】创建Spring配置文件在resources目录下,配置对应类作为Spring管理的bean对象

  • 定义application.xml配置文件并配置StudentDaoImpl



    
    

【第四步】根据容器别名获取Bean对象

package com.zbbmeta;

import com.zbbmeta.dao.StudentDao;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeCycleApplication {
    public static void main(String[] args) {


            //1.根据配置文件application.xml创建IOC容器
            ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
            //2.从IOC容器里面获取id="studentService"对象
            StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
            //3.执行对象方法
            studentDao.save();
            //4.关闭容器
            ac.close();
        
    }
}

打印结果

Spring-1-透彻理解Spring XML的Bean创建--IOC_第9张图片

3 Bean销毁时机

  • 容器关闭前触发bean的销毁

  • 关闭容器方式:
    • 手工关闭容器 调用容器的close()操作

    • 注册关闭钩子(类似于注册一个事件),在虚拟机退出前先关闭容器再退出虚拟机 调用容器的registerShutdownHook()操作

public class LifeCycleApplication {
    public static void main(String[] args) {


            //1.根据配置文件application.xml创建IOC容器
            ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
            //2.从IOC容器里面获取id="studentService"对象
            StudentDao studentDao = (StudentDao) ac.getBean("studentDao");
            //3.执行对象方法
            studentDao.save();
            //4.关闭容器
//            ac.close();
        //注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
        ac.registerShutdownHook();
    }
}

你可能感兴趣的:(JavaWeb,spring,xml,数据库)