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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Shiro 框架简单介绍

    Shiro 框架简单介绍Shiro 框架简单介绍

    2022年4月22日
    39
  • java实现http协议_java用http协议本地文件

    java实现http协议_java用http协议本地文件对于那些感兴趣的人,这是一个片段.我能够通过FluxLauncher而不是reactor-nettyUDP类来实现.privatestaticfinalStringSSDP_IP=”239.255.255.250″;privatestaticfinalintSSDP_PORT=1900;privatestaticfinalintTIMEOUT=500…

    2022年10月11日
    2
  • 【停更】Deepfacelab 新手教程

    【停更】Deepfacelab 新手教程欢迎进入本教程,本教程不定期更新本文教程内容更新时间为:2019/2,本文最后更新时间为:2019/3/8欢迎进群讨论,我不是群主,群主的各QQ群号码请看:https://deepfakes.com.cn/index.php/资助升级群这几天朱茵换脸杨幂的事件上了热门,我们群不存在该违法问题。然而因为网上的这个事件,2群排队已经可以说排到了明年。群主表示等风波结束了再考虑新群,毕竟群主不想…

    2022年5月4日
    112
  • springboot实现ajax跨域请求

    springboot实现ajax跨域请求有段时间没写文章了。看到有人提问ajax跨域请求的问题。博主要再次强调,跨域,就是从不同的的IP端口获取数据,比如说,从www.baidu.com获取数据,就叫跨域!那么localhost:8080与localhost:8081之间呢?也叫跨域。如果处理的不好,就会报错,不仅前端报错,后端也会报错。那么如何解决呢?着急的人,请直接往下看,不急的请听我细细道来,一定能解决您的问题。我再此保证

    2022年6月17日
    36
  • 把一个数据表导入另一个数据库_把一个表里的数据导入另一个表

    把一个数据表导入另一个数据库_把一个表里的数据导入另一个表文章作者:姜南(Slyar)文章来源:SlyarHome(www.slyar.com)转载请注明,谢谢合作。之前发了《表达式变量批量替换器batchSQL》这篇文章,有童鞋说导入数据用phpMyAdmin提供的csv导入功能不是更好。的确,导入数据进入mysql用这个功能非常好,不过如果需要进行批量操作的是update或者其他操作呢,例如要从新的excel里批量更新某一部分的数据,总不能全…

    2022年9月2日
    2
  • 光纤及光纤接入设备[通俗易懂]

    光纤及光纤接入设备[通俗易懂]全面了解光纤接入设备及使用图解由于不同种类信息的需求也越来越多,伴随而来的不断增长的IP数据、话音、多媒体图像等多种新业务需求,促使了各大网络运营商的传送网络环境发生了翻天俯地的变化,以前那些以承载模拟话音为主要目的的传统城域网和接入网在容量以及接口种类上都已经无法满足多种多样的新业务传输与处理的要求。于是迫于社会信息量的突飞猛进,那些专门为城域网和接入…

    2025年5月22日
    0

发表回复

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

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