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)


相关推荐

  • 浮点数规格化表示例题_浮点数规格化阶码表示

    浮点数规格化表示例题_浮点数规格化阶码表示一、浮点数的表示格式浮点数表示法是指以适当的形式将比例因子表示在数据中,让小数点的位置根据需要而浮动。这样,在位数有限的情况下,既扩大了数的表示范围,又保持了数的有效精度。阶码:阶码是整数,阶符和m位阶码的数值部分共同反映浮点数的表示范围及小数点的实际位置,常用移码或补码表示。IEEE754标准中采用移码的表示形式。尾数:数符表示浮点数的符号,尾数的数值部分的位数n反映浮点…

    2022年10月31日
  • 函数的凹凸性_函数凹凸性与图像

    函数的凹凸性_函数凹凸性与图像设函数$f(x)$在区间$I$上有定义,在$I$内任取两点$x_{1},x_{2}$,对任意的 $\lambda\in(0,1)$,有 $\lambdax_{1

  • OAM协议详解_服务期限怎么填写

    OAM协议详解_服务期限怎么填写OAMPDU消息格式及定义OAMPDU消息的格式如下图6-8所示。各个字段的详细定义如下:a) 目的地址(DA):Slow_Protocols_Multicast地址,使用和编码规定见IEEE802.3-2005Annex43B;b) 源地址(SA):OAMPDU中的SA是独立的MAC地址,该地址与发送OAMPDU的端口相关联;c) Length/Type:OAMPDU采

    2022年10月23日
  • 你还在用命令看日志?用这款可视化工具简直太方便了!

    点击上方“全栈程序员社区”,星标公众号 重磅干货,第一时间送达 作者:废物大师兄 cnblogs.com/cjsblog/p/9476813.html Kibana是一个开源的分析…

  • mybatiscodehelperpro2.8.3激活码_navicat premium激活

    mybatiscodehelperpro2.8.3激活码_navicat premium激活目录一、前言二、安装插件MyBatisCodeHelperPro插件三、激活一、前言在开发中编写生成bean,mapper,mapper.xml即费时也费力,可以通过MyBatisCodeHelperPro自动生成bean,dao,mapper.xml等文件,然后根据自己的需要进行修改。MyBatisCodeHelperPro是IDEA下的一个插件,类似于mybatisplugin,但是是收费的,但可以进行激活使用:下面这个大佬的个人主页上有多个版本的下载链…

  • 更新Ubuntu软件源

    更新Ubuntu软件源在Ubuntu操作系统下更换软件源,加快下载速度。

发表回复

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

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