美文网首页Spring boot
Spring bean的生命周期

Spring bean的生命周期

作者: 三也视界 | 来源:发表于2020-11-17 09:15 被阅读0次

@scope 申明bean的作用范围

1. 创建Car

public class Car {
    private String name;
    private int price;
    
    public Car(){
        System.out.println("car constructor...");
    }
}

2.将Car放入bean中管理

public class MainConfig {
    @Bean
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
}

3.启动spring容器

@Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
     
    }

运行结果如下

image

因此spring注册组件默认是在创建IOC容器的时候创建的

将启动spring容器的代码中创建两个car

@Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
        Car car1 = applicationContext.getBean(Car.class);
        Car car2 = applicationContext.getBean(Car.class);
        System.out.println(car1==car2);
    }

运行结果如下

image

因此,可知bean默认是单例的。在创建IOC容器的时候创建的,每当获取的时候都是同一个实例。

当在配置中添加@Lazy的时候,对相应的组件将会实行懒加载。调用的时候才会去实现初始化。

配置修改如下

public class MainConfig {
 
    @Bean
    @Lazy
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
}

运行结果如下

image

从结果可看出,懒加载的时候。调用时才回去加载bean。并且只加载一次。

spring有如下四种作用域

prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,request:同一次请求创建一个实例session:同一个session创建一个实例

可以用@Scope申明Bean的生命周期
spring @Scope注解

修改配置成如下

public class MainConfig {
 
    @Scope("prototype")
    @Bean
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }

再次运行

image

由结果可知。原型模式。spring初始化的时候并未去加载bean。而是在每次调用的时候再去加载。为多实例。

Spring bean的生命周期

bean的生命周期:bean创建—初始化----销毁的过程容器管理bean的生命周期:我们可以自定义初始化和销毁方法;容器在bean进行到当>前生命周期的时候来调用我们自定义的初始化和销毁方法

1.指定初始化和销毁方法

在申明组件的时候,加上初始化和销毁的方法

public class Car  {
    private String name;
    private int price;
    
    public Car(){
        System.out.println("car constructor...");
    }
    
    public void init(){
        System.out.println("car ... init...");
    }
    
    public void destroy(){
        System.out.println("car ... destroy...");
    }
 
}

通过@Bean指定init-method和destroy-method

public class MainConfig {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
}

开启和销毁容器

 @Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
        Car car1 = applicationContext.getBean(Car.class);
 
        ((AnnotationConfigApplicationContext) applicationContext).close();
    }

运行结果如下图

image

由图可知:在组件创建的时候init方法被调用。在组件销毁的时候,destroy方法被调用。

当组件被申明为原型模式

public class MainConfig {
 
    @Scope("prototype")
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }

运行结果如下图所示

image

从结果可看出,如果bean是多实例,spring只负责创建Bean,在容器关闭时并不销毁bean。

实现InitializingBean(定义初始化逻辑) DisposableBean(定义销毁逻辑)

代码如下

public class Car implements InitializingBean, DisposableBean {
    private String name;
    private int price;
    
    public Car(){
        System.out.println("car constructor...");
    }
    
    @Override
    public void destroy(){
        System.out.println("car ... destroy...");
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car ... afterPropertiesSet...");
 
    }
}

运行结果如下

image

BeanPostProcessor

BeanPostProcessor,针对所有Spring上下文中所有的bean,配置一个BeanPostProcessor,然后对所有的bean进行一个初始化之前和之后的代理。BeanPostProcessor接口中有两个方法: postProcessBeforeInitialization和postProcessAfterInitialization。 postProcessBeforeInitialization方法在bean初始化之前执行, postProcessAfterInitialization方法在bean初始化之后执行。

1.创建MyBeanPostProcessor继承BeanPostProcessor接口,重写postProcessBeforeInitialization和postProcessAfterInitialization两个方法。

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("------------------------------");
        System.out.println("对象------" + beanName + "postProcessBeforeInitialization-----"+bean);
        return bean;
    }
 
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("------------------------------");
        System.out.println("对象-----" + beanName + "postProcessAfterInitialization-----"+bean);
        return bean;
    }
}

2.将MyBeanPostProcessor加入容器管理

@Configuration
public class MainConfig {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        System.out.println("add bean car into spring");
        return new Car();
    }
    
    @Bean
    public MyBeanPostProcessor myBeanPostProcessor(){
        return new MyBeanPostProcessor();
    }
}

3.启动spring容器

    @Test
    public  void test04(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        System.out.println("IOC started");
        Car car1 = applicationContext.getBean(Car.class);
 
        ((AnnotationConfigApplicationContext) applicationContext).close();
    }

运行结果如下图

image

由结果可知:在每个bean的初始化前后都调用了BeanPostProcessor

相关文章

网友评论

    本文标题:Spring bean的生命周期

    本文链接:https://www.haomeiwen.com/subject/snsovktx.html