Spring(三)对bean的详解

一、引入外部属性文件

首先我们将依赖进行导入:

 
        
            mysql
            mysql-connector-java
            8.0.22
        
        
        
            com.alibaba
            druid
            1.0.31
        

我们所载入的bean如下所示:

  
        
        
        
        
    

除此之外,我们进行查看其它标签:

        
        
        
        
        
        

我们进行测试:

public class DataSourceTest {
    @Test
    public  void  testDataSource() throws SQLException {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-datasource.xml");
        DruidDataSource dataSource = ioc.getBean(DruidDataSource.class);
        System.out.println(dataSource.getConnection());
    }
}

 我们进行测试之后如下所示:

Spring(三)对bean的详解_第1张图片

 持此之外,IOC也可以利用读取·文件进行引入:

我们创建jdbc.properties文件,如下所示:

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

我们在IOC里面进行引入:


   
    
        
        
        
        
    

我们进行测试:

public class DataSourceTest {
    @Test
    public  void  testDataSource() throws SQLException {
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-datasource.xml");
        DruidDataSource dataSource = ioc.getBean(DruidDataSource.class);
        System.out.println(dataSource.getConnection());
    }
}

我们运行完之后如下所示:

Spring(三)对bean的详解_第2张图片

二、bean的作用域:

 在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,各取值含义如下表所示:

取值 含义 创建对象的时机
singleton(默认) 在IOC容器中,这个bean的对象始终为单实例 IOC容器初始化时
prototype 这个bean在IOC容器中有多个实例 获取bean时

我们载入的bean如下所示:


    
    

我们进行测试如下所示:

public class ScopeTest {
    @Test
    public  void  testScope(){
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-scope.xml");
        Student student1 = ioc.getBean(Student.class);
        Student student2 = ioc.getBean(Student.class);
        System.out.println(student1==student2);
    }

运行之后如下所示:

Spring(三)对bean的详解_第3张图片

我们发现默认为单例模式。

我们利用scope进行设置:


    
    

 我们继续进行测试,发现如下所示:

Spring(三)对bean的详解_第4张图片

此时即不再为单例模式,而是多例模式。 


    
    
    

如果在WebApplicationContext环境下还会有另外两个作用域(但不常用):

取值 含义
request 在一个请求范围内有效
session 在一个会话范围内有效

三、bean的生命周期

具体的生命周期过程

bean对象创建(调用无参构造器)

给bean对象设置属性

bean对象初始化之前操作(由bean的后置处理器负责)

bean对象初始化(需要配置bean时指定初始化方法)

bean对象初始化之后操作(由bean的后置处理器负责)

bean对象就绪可以使用

bean对象销毁(需要配置bean时指定销毁方法)

IOC容器关闭

我们创建如下类所示:

package com.rgf.spring.pojo;

public class User {
    private  Integer id;
    private  String username;
    private  String password;
    private  Integer age;

    public User(Integer id, String username, String password, Integer age) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.age = age;
    }

    public User() {
        System.out.println("生命周期1:实例化");
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        System.out.println("生命周期2:依赖注入");
        this.id = id;

    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                '}';
    }

    public  void  initMethod(){
        System.out.println("生命周期3:初始化");
    }

    public void  destroyMethod(){
        System.out.println("生命周期4:销毁");
    }
}

我们进行注入bean:





    
        
        
        
        
    

测试如下所示:

package com.rgf.spring.test;

import com.rgf.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeCycleTest {
    /**
     * 1.实例化
     * 2.依赖注入
     * 3.初始化,需要通过bean的init-method属性指定初始化的方法
     * 4.IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
     */
    @Test
    public  void  test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();

    }
}

运行之后如下所示:
Spring(三)对bean的详解_第5张图片

 bean的后置处理器:

 bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到IOC容器中,需要注意的是,bean后置处理器不是单独针对某一个bean生效,而是针对IOC容器中所有bean都会执行。

我们进行创建该方法:

package com.rgf.spring.process;

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

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //此方法在bean的生命周期初始化之前执行
        System.out.println("MyBeanPostProcessor-->后置处理器postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // //此方法在bean的生命周期初始化之后执行
        System.out.println("MyBeanPostProcessor-->后置处理器postProcessAfterInitialization");
        return bean;
    }
}

我们进行载入bean里面:

 

此时我们继续进行测试:

package com.rgf.spring.test;

import com.rgf.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LifeCycleTest {
    /**
     * 1.实例化
     * 2.依赖注入
     * 3.后置处理器的postProcessBeforeInitialization方法
     * 4.初始化,需要通过bean的init-method属性指定初始化的方法
     * 5.后置处理器的postProcessAfterInitialization方法
     * 6.IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
     * 注意:
     * 若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
     * 若bean的作用域为多例时,生命周期的前三个步骤会在获取bean时执行
     */
    @Test
    public  void  test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();

    }
}

我们运行之后如下所示:

Spring(三)对bean的详解_第6张图片

四、bean的作用域对生命周期的影响和后置处理器

 当为单例模式的时候,我们在获取IOC的时候直接就进行了初始化:

Spring(三)对bean的详解_第7张图片

 当我们设置为多例模式的时候:


        
        
        
        
    

我们再次执行如下所示:

Spring(三)对bean的详解_第8张图片

 我们发现此时bean没有初始化,因为有多个对象,所以没有必要刚开始就进行bean初始化。

我们继续进行如下测试:

 @Test
    public  void  test(){
        //ConfigurableApplicationContext是ApplicationContext的子接口,其中扩展了刷新和关闭容器的方法
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-lifecycle.xml");
        User user = ioc.getBean(User.class);
        System.out.println(user);
        ioc.close();

    }

运行之后如下所示:
Spring(三)对bean的详解_第9张图片

我们发现当我们在bean里面设置为多例的时候,此时ioc没有进行销毁。此时的销毁的方法则不再由IOC容器来进行管理。 

 /**
     * 1.实例化
     * 2.依赖注入
     * 3.后置处理器的postProcessBeforeInitialization方法
     * 4.初始化,需要通过bean的init-method属性指定初始化的方法
     * 5.后置处理器的postProcessAfterInitialization方法
     * 6.IOC容器关闭时销毁,需要通过bean的destroy-method属性指定销毁的方法
     * 注意:
     * 若bean的作用域为单例时,生命周期的前三个步骤会在获取IOC容器时执行
     * 若bean的作用域为多例时,生命周期的前三个步骤会在获取bean时执行
     */

 五、FactoryBean

FactoryBean是Spring提供的一种整合第三方框架的常用机制,和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值,通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。

我们进行创建UserFactoryBean,

package com.rgf.spring.factory;

import com.rgf.spring.pojo.User;
import org.springframework.beans.factory.FactoryBean;

/**
 * FactoryBean是一个接口,需要创建一个类实现该接口
 * 其中有三个方法:
 * getObject():通过一个对象交给IOC容器管理
 * getObjectType():设置所提供对象的类型
 * isSingleton():所提供的对象是否单例
 * 当把FactoryBean的实现类配置为bean时,会将当前类中getObject()所返回的对象交给IOC容器管理。
 */
public class UserFactoryBean implements FactoryBean {

    @Override
    public User getObject() throws Exception {
        return new User();
    }

    @Override
    public Class getObjectType() {
        return User.class;
    }
}

我们进入FactoryBean,查看是否是单例:

  default boolean isSingleton() {
        return true;
    }

是单例模式

我们将bean进行载入:



  
  

我们进行测试如下所示:

package com.rgf.spring.test;

import com.rgf.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FactoryBeanTest {
    @Test
    public  void  testFactoryBean(){
        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("spring-factory.xml");
        User u = ioc.getBean(User.class);
        System.out.println(u);
    }
}

运行之后如下所示: 

Spring(三)对bean的详解_第10张图片

我们在bean里面没有进行配置该对象,但是最后却获取到了。  

你可能感兴趣的:(Spring,spring,java,mybatis)