Spring Bean的生命周期解读

这篇具有很好参考价值的文章主要介绍了Spring Bean的生命周期解读。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

 文章来源地址https://www.toymoban.com/news/detail-511777.html

1. Spring IOC容器

1.1 Spring IOC 容器的设计

1.1.1 BeanFactory

1.1.2 ApplicationContext

1.2 Spring Bean的生命周期

1.2.1 BeanDefinition

1.2.2 InstantiationAwareBeanPostProcessor和BeanPostProcessor

1.2.3 测试生命周期


 

1. Spring IOC容器

1.1 Spring IOC 容器的设计

Spring IOC 容器的设计主要是基于BeanFactoryApplicationContext两个接口,其中ApplicationContext是BeanFactory的子接口之一,换句话说BeanFactory是Spring IOC容器所定义的最顶层接口,而ApplicationContext是其高级接口之一,并且对于BeanFactory功能做了许多有用的扩展,所以在绝大部分的工作场景中,都会使用ApplicationContext作为Spring IOC 容器,如下图所示:

Spring Bean的生命周期解读

 首先我们定义一个User实体类:

public class User {
    String username;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }
}

1.1.1 BeanFactory

BeanFactory的使用注册Bean对象以及获取Bean对象代码如下:

DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
        RootBeanDefinition rootBeanDefinition=new RootBeanDefinition(User.class);
        beanFactory.registerBeanDefinition("user",rootBeanDefinition);
        System.out.println(beanFactory.getBean("user",User.class));

1.1.2 ApplicationContext

ApplicationContext的使用注册Bean对象以及获取Bean对象代码如下:

 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(User.class);
        applicationContext.refresh();
        System.out.println(applicationContext.getBean("user", User.class));

1.2 Spring Bean的生命周期

Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。

而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期。

生命周期主要是为了了解Spring IOC容器初始化和销毁Bean的过程,通过对它的学习就可以知道如何在初始化和销毁的时候加入自定义的方法,以满足特定的需求。如下图:

Spring Bean的生命周期解读

 

从上图可以看到,Spring IoC容器对Bean 的管理还是比较复杂的,Spring loC容器在执行了初始化和依赖注入后,会执行一定的步骤来完成初始化,通过这些步骤我们就能自定义初始化,而在Spring IoC 容器正常关闭的时候,它也会执行一定的步骤来关闭容器,释放资源。除需要了解整个生命周期的步骤外,还要知道这些生命周期的接口是针对什么而言的,首先介绍生命周期的步骤。

1. 如果 Bean 实现了接口 BeanNameAware的setBeanName方法,那么它就会调用这个方法。
2. 如果 Bean 实现了接口 BeanFactoryAware 的 setBeanFactory方法,那么它就会调用这个方法。
3. 如果 Bean实现了接口 ApplicationContextAware 的 setApplicationContext方法,且
Spring loC容器也必须是一个ApplicationContext 接口的实现类,那么才会调用这个方法,否则是不调用的。
4. 如果 Bean 实现了接口 BeanPostProcessor 的 postProcessBeforeInitialization方法,那么它就会调用这个方法。

5 .如果 Bean实现了接口BeanFactoryPostProcessor的afterPropertiesSet方法,那么它就会调用这个方法。
6. 如果 Bean自定义了初始化方法,它就会调用已定义的初始化方法。
7. 如果Bean 实现了接口 BeanPostProcessor 的postProcessAfterInitialization方法,完成了这些调用,这个时候Bean 就完成了初始化,那么 Bean就生存在Spring loC的容器中了,使用者就可以从中获取 Bean的服务。
8. 当服务器正常关闭,或者遇到其他关闭 Spring loC 容器的事件,它就会调用对应的方完成Bean 的销毁,其步骤如下:
        如果Bean实现了接口 DisposableBean 的 destroy方法,那么就会调用它。
        如果定义了自定义的销毁方法,那么就会调用它。

1.2.1 BeanDefinition

Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构。不管是是通过xml配置文件的<Bean>标签,还是通过注解配置的@Bean,还是@Compontent标注的类,还是扫描得到的类,它最终都会被解析成一个BeanDefinition对象,最后我们的Bean工厂就会根据这份Bean的定义信息,对bean进行实例化、初始化等等操作。

你可以把BeanDefinition丢给Bean工厂,然后Bean工厂就会根据这个信息帮你生产一个Bean实例,拿去使用。

BeanDefinition里面里面包含了bean定义的各种信息,如:bean对应的class、scope、lazy信息、dependOn信息、autowireCandidate(是否是候选对象)、primary(是否是主要的候选者)等信息。

Spring Bean的生命周期解读

 RootBeanDefinition类:表示根bean定义信息,通常bean中没有父bean的就使用这种表示。

ChildBeanDefinition类:表示子bean定义信息,如果需要指定父bean的,可以使用ChildBeanDefinition来定义子bean的配置信息,里面有parentName属性,用来指定父bean的名称。

GenericBeanDefinition类:通用的bean定义信息,既可以表示没有父bean的bean配置信息,也可以表示有父bean的子bean配置信息,这个类里面也有parentName属性,用来指定父bean的名称。

ConfigurationClassBeanDefinition类:表示通过配置类中@Bean方法定义bean信息

可以通过配置类中使用@Bean来标注一些方法,通过这些方法来定义bean,这些方法配置的bean信息最后会转换为ConfigurationClassBeanDefinition类型的对象。

AnnotatedBeanDefinition接口:表示通过注解的方式定义的bean信息。

BeanDefinitionBuilder:构建BeanDefinition的工具类

1.2.2 InstantiationAwareBeanPostProcessor和BeanPostProcessor

 

InstantiationAwareBeanPostProcessor实际上继承了BeanPostProcessor接口。InstantiationAwareBeanPostProcessor作用于实例化阶段的前后,BeanPostProcessor作用于初始化阶段的前后。如下图:

Spring Bean的生命周期解读

 BeanPostProcessor是一个接口,还有很多子接口,这些接口中提供了很多方法,spring在bean生命周期的不同阶段,会调用BeanPostProcessor中的一些方法,来对生命周期进行扩展,bean生命周期中的所有扩展点都是依靠这个集合中的BeanPostProcessor来实现的。该接口提供了两个函数:postProcessBeforeInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会先于InitialzationBean执行,因此称为前置处理。 所有Aware接口的注入就是在这一步完成的。postProcessAfterInitialzation( Object bean, String beanName ) 当前正在初始化的bean对象会被传递进来,我们就可以对这个bean作任何处理。 这个函数会在InitialzationBean完成后执行,因此称为后置处理。


Spring Aware是Spring定义的回调接口。何为回调?就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个函数B,对于C来说,这个B便叫做回调函数。

1.2.3 测试生命周期

我们自定义一个User实体类,要求Spring容器使用我们自定义的@MyAutowired注解标注的构造方法进行构造Bean对象,然后我们观察在Bean周期的日志打印,更好的理解Bean周期过程。

自定义@MyAutowired注解

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.CONSTRUCTOR)
public @interface MyAutowired {
}

定义User实体类

public class User implements InitializingBean, DisposableBean {
    String username;
    //Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,
    // 该属性指定了在这一阶段需要执行的函数名。Spring便会在初始化阶段执行我们设置的函数。
    // init-method本质上仍然使用了InitializingBean接口。
    public void init(){
        System.out.println(this.getClass().getSimpleName()+" 执行自定义初始化方法");
    }

    public User() {
    }

    @MyAutowired
    public User(String username) {
        this.username = username;
    }


    public String getUsername() {
        return username;
    }

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

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

    @Override
    public void destroy() throws Exception {
        System.out.println("调用DisposableBean接口的destroy方法");
    }
    //afterPropertiesSet()这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,
    // 但它与前置处理不同,由于该函数并不会把当前bean对象传进来,因此在这一步没办法处理对象本身,
    // 只能增加一些额外的逻辑。 若要使用它,我们需要让bean实现该接口,把要增加的逻辑写在该函数中。
    // 然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用afterPropertiesSet方法");
    }
}

测试代码

public class MyTest {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
        //InstantiationAwareBeanPostProcessor接口在Bean对象实例化前的方法
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
                if(beanName.equals("user"))
                System.out.println(beanName+" Bean对象在实例化之前操作**");
                return null;
            }
        });
        //InstantiationAwareBeanPostProcessor接口在Bean对象实例化后的方法
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
                if(beanName.equals("user"))
                System.out.println(beanName+" Bean对象在实例化之后操作**");
                return false;
            }
        });
        //使用自己自定义含有@MyAutowired注解的构造方法,实例化Bean对象
        beanFactory.addBeanPostProcessor(new SmartInstantiationAwareBeanPostProcessor() {
            public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
                if(beanName.equals("user"))
                System.out.println("实例化Bean对象");
                Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
                List<Constructor<?>> collect = Arrays.stream(declaredConstructors).filter(i -> i.isAnnotationPresent(MyAutowired.class)).collect(Collectors.toList());
                Constructor[] constructors = collect.toArray(new Constructor[collect.size()]);
                return constructors.length>0?constructors:null;

            }
        });
        //BeanPostProcessor接口在Bean对象初始化之前的方法调用
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if(beanName.equals("user"))
                    System.out.println(beanName+" Bean对象在初始化之前操作**");
                return null;
            }
        });
       //BeanPostProcessor接口在Bean对象初始化之后的方法调用
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if(beanName.equals("user"))
                    System.out.println(beanName+" Bean对象在初始化之后操作**");
                return null;
            }
        });

        RootBeanDefinition rootBeanDefinition= (RootBeanDefinition) BeanDefinitionBuilder.rootBeanDefinition(User.class).setInitMethodName("init").getBeanDefinition();
        beanFactory.registerBeanDefinition("user",rootBeanDefinition);
        beanFactory.registerBeanDefinition("username", BeanDefinitionBuilder.genericBeanDefinition(String.class)
                .addConstructorArgValue("admin").getBeanDefinition());
        System.out.println(beanFactory.getBean("user",User.class));
        beanFactory.destroySingletons();


    }
}

测试截图

Spring Bean的生命周期解读

至此这篇文章到此结束。

Spring Bean的生命周期解读

 

 

到了这里,关于Spring Bean的生命周期解读的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【spring】spring bean的生命周期

    spring bean的生命周期 简介 本文测试并且介绍了spring中bean的生命周期,如果只想知道结果可以跳到最后一部分直接查看。 一、bean的创建阶段 spring中的bean是何时创建的? 在spring中有一个非常重要的注解,叫做**@Scope**,这个注解是用来控制spring中的bean是否是单例的,一般情况

    2024年02月15日
    浏览(52)
  • Spring Bean的生命周期

    Bean生命周期的整个执行过程描述如下: 1、根据配置情况调用Bean构造方法或工厂方法实例化 Bean。 2、利用依赖注入完成Bean中所有属性值的配置注入。 3、如果Bean 实现了BeanNameAware 接口,则 Spring调用Bean的setBeanName()方法传入当前Bean的id值。 4、如果Bean实现了BeanFactoryAware 接口

    2023年04月22日
    浏览(65)
  • Spring -- Bean的生命周期

    Spring容器在进行实例化时,会将xml配置的bean的信息封装成一个BeanDefinition对象,Spring根据BeanDefinition来创建Bean对象,里面有很多的属性用来描述Bean   BeanDefinition 中几个重要方法如下 beanClassName:bean 的类名 initMethodName:初始化方法名称 properryValues:bean 的属性值 scope:作用域

    2024年02月15日
    浏览(54)
  • 【Spring】Spring的Bean的生命周期

    作者简介:大家好,我是五度鱼,一个普通的Java领域博主,不停输出Java技术博客和干货 。 座右铭:锲而不舍,金石可镂 。 个人主页:五度鱼学Java的主页 在 Java 中, Bean 是一个重要的概念,它代表了应用程序中的一个对象。在开发中,我们经常使用 Bean 来管理对象的生命

    2024年01月16日
    浏览(58)
  • Spring整理-Spring Bean的生命周期

    Spring Bean的生命周期涉及多个阶段,从Bean的定义到其销毁。在这个过程中,Spring容器负责创建、初始化、使用和最终销毁Bean。了解这个生命周期有助于更好地管理Bean的行为和资源使用。 实例化(Instantiation): 容器首先创建Bean的实例。 填充属性(Populate Properties): 容器

    2024年01月21日
    浏览(53)
  • Spring源码:Bean生命周期(五)

    在上一篇文章中,我们深入探讨了 Spring 框架中 Bean 的实例化过程,该过程包括从 Bean 定义中加载当前类、寻找所有实现了 InstantiationAwareBeanPostProcessor 接口的类并调用实例化前的方法、进行实例化、调用 applyMergedBeanDefinitionPostProcessors 方法等多个步骤,最终生成了一个真正的

    2024年02月04日
    浏览(43)
  • Spring中 Bean的生命周期

    如果把Spring看做一个大型工厂,则Spring容器中的Bean就是该工厂的产品。要想使用这个工厂生产和管理Bean,就需要在配置文件中告诉它需要哪些Bean,以及需要使用何种方式将这些Bean装配到一起。 Bean的本质就是Java中的类,而Spring中的Bean其实就是对实体类的引用,来生产Java类

    2024年01月24日
    浏览(40)
  • Spring源码:Bean生命周期(终章)

    本系列前面讲解了Spring的bean定义、bean实例化、bean初始化等生命周期。这些步骤使我们能够了解bean从创建到准备好使用所经历的过程。但是,除了这些步骤,bean的销毁也是非常重要的一步。在本系列的最后,我们将深入探讨bean的销毁过程,包括在什么情况下会发生销毁、销

    2024年02月06日
    浏览(53)
  • Spring(11) Bean的生命周期

    首先,为什么要学习 Spring 中 Bean 的生命周期呢? 虽然不了解 Bean 的生命周期,并不影响日常工作中的开发。但是如果我们了解了 Bean 的生命周期,可以帮助我们更好地掌握 Spring 框架,并且能够让我们更好地去理解 Spring 容器是如何管理和创建 Bean 示例的。如果以后遇到 B

    2024年02月14日
    浏览(37)
  • 详解Spring Bean的生命周期

    Spring Bean的生命周期包括以下阶段: 1. 实例化Bean 对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBean进行实例化。 对于ApplicationContext容器,当容器启动结束后,便实例化所有的bean。

    2024年02月14日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包