Spring5——IOC操作Bean管理(基于xml文件)


前言

最近在学习Spring5框架,下面关于Spring5之IOC容器管理Bean的学习笔记和心得,如有错误,欢迎指正。

学习资源:

尚硅谷Spring5框架教程(idea版)

IOC容器

控制反转(IOC)。IOC容器就是具有依赖注入功能的容器,面向对象中的一种设计原则,可以降低代码之间的耦合度。通过IOC,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所有依赖的对象的引用传递给它,即依赖被注入到对象中。

通俗点来讲,就是通过IOC我们可以使用第三方工具来创建对象,而不必再使用传统方法 new 一个对象,并且可以通过IOC容器将其他对象、属性注入到需要创建的对象中去,这一切都交给IOC进行管理,大大降低代码的耦合度。

  • 把对象的创建和对象之间调用的操作都交给Spring进行管理;
  • 使用IOC的目的:降低耦合度;

IOC底层原理

  • xml解析、工厂模式、反射

IOC接口(BeanFactory)

IOC的思想要基于IOC的容器来完成,本质上就是对象工厂(主要还是要实现 BeanFactory 这个接口);

Spring中对于容器的实现提供了两种方法(也就是两个接口):

  • BeanFactory:IOC容器内部使用的接口,一般不提供给开发人员使用(加载配置文件的时候,不会创建对象,而是在获取对象(使用对象)的时候才去创建对象);
  • ApplicationContext:BeanFactory的子接口,提供更强大的功能,一般给开发人员进行使用(加载配置文件的时候,就会将配置文件中对象进行创建)。
  • l两者都可以加载配置文件,创建对象
  • ApplicationContext中接口有实现类

IOC操作Bean管理(基于xml文件)

创建对象:通过在xml文件中使用bean标签,并且在标签中的属性设置值,我们就可以在Java程序中创建一个对象。

比如下面的配置文件中,我们就创建了一个Users类的对象users,并且可以通过users来调用Users类中的add方法。

<?xml version="1.0" encoding="UTF-8"?>

    

        //在Spring的配置文件中,使用bean标签,并在标签中添加对应的属性,就可以实现对象的创建
        //常用属性
        id属性:给对象起一个标识,可以通过id获得对象
        class属性:写要创建的对象所在的类的全路径
        name属性:与id作用类似,但是id中不能添加特殊符号,id中可以
        //在创建对象的时候默认执行无参构造器
package com.blue.spring5;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/8 21:10
 */
public class TestUsers {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
        Users users = context.getBean("users", Users.class);
        users.add();
    }
}

注入属性

  • 通过xml文件,我们可以在创建对象过程中,将给对象注入需要的属性值。
//DI:依赖注入(注入属性),DI是IOC中的一种具体实现,必须在创建对象的基础上实现

package com.blue.spring5.testDemo;

public class Book {
    private String bName;//书名

    public void setbName(String bName) {
        this.bName = bName;
    }
    public Book(){}
    public Book(String bName) {
        this.bName = bName;
    }

    public static void main(String[] args) {
        //set方法注入
        Book book = new Book();
        book.setbName("西游记");
        System.out.println(book.bName);
        
        //有参构造器参数注入
        Book book = new Book("西游记");
        System.out.println(book.bName);
    }
}

  • 基于Spring的xml配置文件配置对象创建,配置set方法属性注入
 
    
    
        
        
        
  • 基于Spring的xml配置文件配置对象创建,配置参数方法属性注入

    
    
        
        
    
  • 基于Spring的xml配置文件注入空值和特殊符号
    • 字面量:给类中的属性设置的固定值
    • null;
    • 特殊符号。
 
            
                
            
  

注入集合类型属性

可以通过配置文件,将集合类型的数据注入到对象属性中去。

  • 注入数组类型属性

  • 注入List集合类型属性

  • 注入Map集合类型属性

<?xml version="1.0" encoding="UTF-8"?>

    
    
    
        
        
        
            
                语文
                数学
            
        
        
        
            
                张三
                李四
            
        
        
        
            
                
                
            
        
        
        
            
                Redis
                MySQL
            
        
    



package com.blue.spring5.testDemo;


import com.blue.spring5.collectiontype.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@SuppressWarnings({"all"})
/**
 * @Author Blueshadow
 * @Date 2021/10/24 20:55
 * @Version 1.0
 */
public class TestSpring5 {
    @Test
    public void testCourse(){
        ApplicationContext context =
                new ClassPathXmlApplicationContext("bean1.xml");
        Student stu = context.getBean("stu", Student.class);
        stu.testDemo();
    }
}



package com.blue.spring5.collectiontype;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Student {
    //数组类型的属性
    private String[] course;
    private List lists;
    private Map map;//k-v结构
    private Set set;

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

    public void setCourse(String[] course) {
        this.course = course;
    }

    public void setLists(List lists) {
        this.lists = lists;
    }

    public void setMap(Map map) {
        this.map = map;
    }

    public void testDemo(){
        System.out.println(Arrays.toString(course));
        System.out.println(lists);
        System.out.println(map);
        System.out.println(set);
    }
}

注入外部Bean

注入外部bean,就是在xml文件中创建两个对象,然后将其中一个对象注入到另一个对象中去,这种方法可以用于处理业务逻辑层和DAO层之间的对象引用。

  • xml
<?xml version="1.0" encoding="UTF-8"?>



    

        
    
    
    

    
    

  • service
package com.blue.service;

import com.blue.dao.UserDAOImpl;
import com.blue.dao.UserDAOInterface;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/6 16:42
 */
public class UserService {
    //创建 UserDAO 类型属性
    private UserDAOInterface userDAO;

    public UserDAOInterface getUserDAO() {
        return userDAO;
    }

    public void setUserDAO(UserDAOInterface userDAO) {
        this.userDAO = userDAO;
    }

    public void add(){
        System.out.println("Service add ...");
        userDAO.upDate();
    }
}

注入内部Bean和级联赋值

  • 在实体类时间表示一对多的关系
<?xml version="1.0" encoding="UTF-8"?>

    
    
        
        
        

            
                
            
        
    




  • 级联赋值1
<?xml version="1.0" encoding="UTF-8"?>

    
    
        
        

        
    
    
        
    





  • 级联赋值2
<?xml version="1.0" encoding="UTF-8"?>

    
    
        
        

        
        
        
    
    
    





Bean管理

Factory Bean

  • Spring中有两种bean,一种是普通bean,一种是 FactoryBean(工厂bean)
  • 普通bean在配置文件中,定义的对象类型就是返回类型
  • FactoryBean在配置文件中定义的对象类型可以和返回类型不同
package com.blue.factorybean;

import com.blue.colectiontype.Course;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/7 20:15
 * 该类作为一个工厂bean
 */
public class FactoryBean_ implements FactoryBean {

    //自定义要返回的类型
    @Override
    public Course getObject() throws Exception {
        Course course = new Course();
        course.setCname("1906");
        return course;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

Bean的作用域

  • 在Spring中可以设置,创建的ben实例是单实例还是多实例
  • 默认情况下创建的是单实例对象
  • 顾名思义:单实例对象就是一个对象,多实例对象就是两个不同的对象
<?xml version="1.0" encoding="UTF-8"?>


    



package com.blue.scope;

import com.blue.colectiontype.Stu;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/7 20:56
 */
public class Scope_ {
    public static void main(String[] args) {
        new Scope_().testScope();
    }
    public void  testScope(){
        ApplicationContext context = new ClassPathXmlApplicationContext("scope.xml");
        Stu student1 = context.getBean("student", Stu.class);
        Stu student2 = context.getBean("student",Stu.class);
        System.out.println("stu1: "+student1);
        System.out.println("stu2: "+student2);
        //stu1: com.blue.colectiontype.Stu@5f341870
        //stu2: com.blue.colectiontype.Stu@5f341870
    }
}

  • 多实例对象
    • 通过bean标签中的scope属性来设置多实例对象(scope属性值:singleton 单实例对象、prototype 多实例对象)
    • 两者区别
      • singleton 单实例、prototype 多实例
      • 设置singleton时,在加载配置文件过程中,会创建单实例对象
      • 设置prototype时,不是在加载配置文件过程中创建对象,而是在调用 getBean 方法过程中创建对象,即每次创建的都是一个新的对象
<?xml version="1.0" encoding="UTF-8"?>


    



package com.blue.scope;

import com.blue.colectiontype.Stu;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/7 20:56
 */
public class Scope_ {
    public static void main(String[] args) {
        new Scope_().testScope();
    }
    public void  testScope(){
        ApplicationContext context = new ClassPathXmlApplicationContext("scope.xml");
        Stu student1 = context.getBean("student", Stu.class);
        Stu student2 = context.getBean("student",Stu.class);
        System.out.println("stu1: "+student1);
        System.out.println("stu2: "+student2);
        //stu1: com.blue.colectiontype.Stu@f6c48ac
        //stu2: com.blue.colectiontype.Stu@13deb50e
    }
}

Bean的生命周期

  • 对象创建~对象销毁的过程被称作bean的生命周期
    • 通过无参构造器去创建实例;
    • 为bean的属性设置对应的值或者对其他bean的引用(调用set方法);
    • 把bean的实例传递给bean的后置处理器的方法 postProcessBeforeInitialization;
    • 调用bean里面初始化的方法(需要进行配置);
    • 把bean的实例传递给bean的后置处理器的方法 postProcessAfterInitialization;
    • bean可以使用了(对象获取到了);
    • 当容器在关闭的时候,会调用bean中销毁对象的方法(需要进行配置)。
<?xml version="1.0" encoding="UTF-8"?>


    
        
    



package com.blue.lifecycle;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/7 21:18
 */
public class Orders {
    private String oname;
    public Orders() {
        System.out.println("执行了Orders的无参构造器 ...");
    }
    public void setOname(String oname) {
        this.oname = oname;
        System.out.println("调用了setOname 设置属性值 ...");
    }

    //创建执行的初始化方法
    public void initMethod(){
        System.out.println("执行初始化方法 ...");
    }

    //销毁对象的方法
    public void destoryMethod(){
        System.out.println("执行销毁对象方法 ...");
    }

    @Override
    public String toString() {
        return "Orders{" +
                "oname='" + oname + '\'' +
                '}';
    }
}

package com.blue.lifecycle;

import com.sun.xml.internal.ws.api.pipe.ClientTubeAssemblerContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * User: Blueshadow
 * Date&Time: 2021/12/7 21:19
 */
public class TestOrders {
    public static void main(String[] args) {
        new TestOrders().testOrders();
    }
    public void testOrders(){
        ApplicationContext context = new ClassPathXmlApplicationContext("lifecycle.xml");
        Orders orders = context.getBean("orders", Orders.class);
        System.out.println("获取到了创建出来的实例对象 ... "+orders);
        System.out.println(orders);

        //手动销毁实例对象
        ((ClassPathXmlApplicationContext)context).close();
    }
    //执行了Orders的无参构造器 ...
    //调用了setOname 设置属性值 ...
    //执行初始化方法 ...
    //获取到了创建出来的实例对象 ... Orders{oname='vivo'}
    //Orders{oname='vivo'}
    //执行销毁对象方法 ...
}

xml自动装配

  • 手动装配:在xml文件中手动输入要创建的对象的属性值;
  • 自动装配:根据指定的装配规则(属性类型、属性名称),自动将匹配的属性值进行注入
<?xml version="1.0" encoding="UTF-8"?>



    

    
    



外部属性文件

这种操作在连接数据库的过程中会用到,可以将properties配置文件引入到xml文件中,然后在程序中引用xml文件来创建相应的对象。

<?xml version="1.0" encoding="UTF-8"?>



    
        
        






        

        
        
        
        
    



#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
#url=jdbc:mysql://localhost:3306/girls
username=root
password=xxx
#initial connection Size
initialSize=10
#min idle connecton size

minIdle=5
#max active connection size
maxActive=50
#max wait time (5000 mil seconds)
maxWait=5000