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


相关推荐

  • 虚拟机Centos 7 使用命令 ip addr 不显示IP地址[通俗易懂]

    虚拟机Centos 7 使用命令 ip addr 不显示IP地址[通俗易懂]ipaddr不显示地址(如果是在虚拟机运行的,首先考虑VMWareNaTService和VMWareDHCPService)记住这个ens33这个就是一会修改的文件后缀(不同主机的文件可能会不一样) 这个文件在ect/sysconfig/network-scripts目录 在文件路径下找到ifcfg-ens33文件然后进行修改  只需要把ONBOOT=no改为ONBO…

    2022年7月27日
    17
  • 计算机位移指令的作用,循环移位指令有什么作用?

    计算机位移指令的作用,循环移位指令有什么作用?循环移位指令将字节、字或双字中的各位向右或向左循环移动N位后,再送给指令的输出单元。循环移位是环形的,即被移出来的位将返回到另一端空出来的位(见图4-18)。带进位的右、左循环移位指令各位的数据与进位位一起(16位指令时一共17位)向右(或向左)循环移动n位。循环移位指令(1)16位节日彩灯的循环移位控制设计循环移位的16位彩灯控制程序,移位的时间间隔为1s,首次扫描时用M8002来设置彩灯的初…

    2022年5月27日
    43
  • oracle物化视图的刷新命令_物化视图增量刷新

    oracle物化视图的刷新命令_物化视图增量刷新物化视图(MATERIALIZEDVIEW)是一个包含查询结果的数据库对象。将经常使用的数据拷贝并存储下来,在查询时就可以直接返回数据。本质上是一个物理表,会占用磁盘空间。本文主要记录了物化视图刷新的方法、时机等相关特性。

    2025年6月6日
    3
  • UNet详解(附图文和代码实现)

    卷积神经网络被大规模的应用在分类任务中,输出的结果是整个图像的类标签。但是UNet是像素级分类,输出的则是每个像素点的类别,且不同类别的像素会显示不同颜色,UNet常常用在生物医学图像上,而该任务中图片数据往往较少。所以,Ciresan等人训练了一个卷积神经网络,用滑动窗口提供像素的周围区域(patch)作为输入来预测每个像素的类标签。这个网络有两个优点:(1)输出结果可以定位出目标类别的位置;(2)由于输入的训练数据是patches,这样就相当于进行了数据增强,从而解决了生物医学图像数量少的问题。但是,

    2022年4月4日
    226
  • 去除限制 Post 请求大小限制

    去除限制 Post 请求大小限制tomcat6及以下版本 在tomcat文件夹下的conf文件中的server.xml配置中添加: maxPostSize=”0″//0表示不限制大小。tomcat7及以上版本​ 在tomcat文件夹下的conf文件中的server.xml配置中添加:​ maxPostSize=”-1″//-1表示不限制大小。​ maxPostSiz…

    2022年7月18日
    19
  • windows下github 出现Permission denied (publickey).解决方法

    windows下github 出现Permission denied (publickey).解决方法

    2021年10月12日
    78

发表回复

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

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