init-method,@postcontruct,afterPropertiesSet的先后顺序;[通俗易懂]

在牛客面经上遇到的一个面试题。突然想尝试下然后就开始做了测试ApplicationContextapplicationContext=newClassPathXmlApplicationContext("classpath:applicationContext.xml");TestDaotestDao=applicationContext.getBean(TestDao.class);((ClassPathXmlAp

大家好,又见面了,我是你们的朋友全栈君。

在牛客面经上遇到的一个面试题。突然想尝试下 然后就开始做了

测试

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        TestDao testDao = applicationContext.getBean(TestDao.class);
        ((ClassPathXmlApplicationContext) applicationContext).close();

测试的bean

@Component
public class TestDao  implements InitializingBean, DisposableBean {
    public TestDao() {
        System.out.println("constructor");
    }

    @Async
    public void query(){
        System.out.println("Hello Spring!");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("afterPropertiesSet");
    }
    @PostConstruct
    public void PostConstruct(){
        System.out.println("PostConstruct");
    }

    public void InitMethod(){
        System.out.println("InitMethod");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("destroy");
    }
    @PreDestroy
    public void PreDestroy(){
        System.out.println("PreDestroy");
    }
    public void destroyMethod(){
        System.out.println("destroyMethod");
    }
}

xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd

        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
    <bean id="testDao" class="com.test.dao.TestDao" init-method="InitMethod" destroy-method="destroyMethod"></bean>

</beans>

执行之后打印的结果 file 总的来说就是打印的结果是构造方法->注解@PostConstruct方法->InitializingBean接口的afterPropertiesSet方法->xml中配置的init-method方法 同理销毁也是一样注解@PreDestroy方法->DisposableBean接口的destroy方法->xml中配置的destroy-method方法

源码

通过断点调试发现几个初始化方法都定位到了AbstractAutowireCapableBeanFactory的initializeBean方法中

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
        //此处执行的是@PostConstruct注解的方法 InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
        //执行的是afterPropertiesSet和init-method方法
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

后面执行的两个方法 protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
        //执行afterPropertiesSet方法
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
                //执行的是xml中自定义的init-method方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

欢迎搜索关注本人的公众号【微瞰技术】,以及总结的分类面试题https://github.com/zhendiao/JavaInterview

file

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/127461.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 关于fastjson在Object转String时的一个坑

    关于fastjson在Object转String时的一个坑关于fastjson在Object转String时的一个坑背景在公司的业务中有这么一个场景:需要将某个系统的结果对象放进Hbase中,然后被后续系统读取使用,在Hbase存储的时候,需要将对象中每个属性解析成字符串存入,但一开始存入接口的设计者只考虑了普通类型(Integer、Long、String之类)的字段存储,未考虑Map或者POJO对象的存储,因此原始代码如下: … if(O…

    2022年6月5日
    59
  • sourceinsight4.0序列号_source insight 4

    sourceinsight4.0序列号_source insight 4先关闭Souceinsight。打开C:\ProgramData\SourceInsight\4.0\si4.lic将Date和Expiration都加一年(比今年多一年即可),保存。重新打开Souceinsight,会提示重新输入用户名和邮箱,继续试用30days。

    2022年10月3日
    4
  • JSON数组转Java List

    JSON数组转Java List本文使用alibaba开源项目fastjson与SourceForge开源项目JSON-lib两种方法转换json。现有json文件user.json如下:[{“userid”:”309BCCE3-8525-4D33-9856-5084E24FD96F”,”username”:”林梦”,”password”:”19bdec7440acd44c669

    2022年8月23日
    5
  • javaWeb前后台交互(Jdbc+Jsp+Servlet+mysql)

    javaWeb前后台交互(Jdbc+Jsp+Servlet+mysql)最近翻看以前的笔记,想到以前自己学习完servlet+jsp+mysql却怎么也把前后台连接不上,最后自己折腾好几天,终于搭建成功,写这个笔记也算是记录一下,代码是那个时候的代码,现在稍微加工了下。可以照下面步骤先把前后台连接上,有点成就感,给自己打打气加油加油,然后再研究代码怎么写的。毕竟都是从那个时候爬(自学坑太多)过来的。(这段话只是针对你我等小白,大神请自动忽略,谢谢配合)这次就写最简…

    2022年6月13日
    20
  • 大数据分析-用户画像详解

    转自:百丽百灵(ID:BL100BL)转自数据分析公号,来源:数据客什么是用户画像?用户画像(UserProfile),作为大数据的根基,它完美地抽象出一个用户的信息全貌,为进一步精准、快速地分析用户行为习惯、消费习惯等重要信息,提供了足够的数据基础,奠定了大数据时代的基石。用户画像,即用户信息标签化,就是企业通过收集与分

    2022年4月6日
    33
  • rtsp、rtmp测试地址

    rtsp、rtmp测试地址有时需要rtsp、rtmp测试地址时,网上搜出来的都是千篇一律的已停用的测试地址,因此在这里维护一个播放列表,随缘更新(发现新的地址可以在评论区留言)【lastupdate】2022/07/01

    2022年10月20日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号