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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • module ‘tensorflow’ has no attribute ‘placeholder’

    module ‘tensorflow’ has no attribute ‘placeholder’tensorflow2.0提示错误:module’tensorflow’hasnoattribute’placeholder’解决办法:不要使用:importtensorflowastf替换为:importtensorflow.compat.v1astftf.disable_v2_behavior()tensorflow的新变化,后续查到具体的文档,再补…

  • seekg的应用案例

    seekg的应用案例在学习C++文件流控制时(链接)我们知道C++有一个标准库fstream该库定义了三个数据类型ofstreamifstream和fstream在练习相应的案例时,seekg()函数掌握的不是很好,后经过多次尝试,可以正常调用了代码如下:#include<fstream>#include<iostream>usingnamespacestd;intmain(){chardata[100];////以写模式打开文件

  • Merge into用法总结

    Merge into用法总结简单的说就是,判断表中有没有符合on()条件中的数据,有了就更新数据,没有就插入数据。  有一个表T,有两个字段a、b,我们想在表T中做Insert/Update,如果条件满足,则更新T中b的值,否则在T中插入一条记录。在Microsoft的SQL语法中,很简单的一句判断就可以了,SQLServer中的语法如下:  ifexists(select1fromTwhere…

  • TTL与RS-232电平转换芯片MAX232/MAX3232「建议收藏」

    TTL与RS-232电平转换芯片MAX232/MAX3232「建议收藏」TTL电平标准:输出L:2.4V             输入L:2.0V RS-232标准:逻辑1的电平为-3~-15V,逻辑0的电平为+3~+15V    MAX232供电电压只能是5V的,也就是说对于3.3V的系统,最好采用宽电压的MAX3232,电压范围3V~5V,而管脚是兼容的,只是电容的选取有所不同。 电容的选取如下:

  • linux启动sh文件命令,Linux 运行 .sh 文件的两种方法「建议收藏」

    linux启动sh文件命令,Linux 运行 .sh 文件的两种方法「建议收藏」Linux运行.sh文件的两种方法文章作者:网友投稿 发布时间:2010-06-1513:31:16 来源:网络一个中等水平的Linux用户一定少不了经常执行.sh文件,当然了,你可以在图形界面下面直接双击该文件,但无疑比较浪费时间。现在介绍第一种方法:(在ubuntu下的)首先你要打开一个终端。然后输入sudosu随后输入密码。这样就取得了root用户权限。然后找到那个文件(…

    2022年10月28日
  • 窗体在任务栏显示 MFC「建议收藏」

    窗体在任务栏显示 MFC「建议收藏」在窗体初始里面加入代码:ModifyStyleEx(0, WS_EX_APPWINDOW);

发表回复

您的电子邮箱地址不会被公开。

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