zoukankan      html  css  js  c++  java
  • init-method,@postcontruct,afterPropertiesSet的先后顺序

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

    测试

    		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);
    		}
    	}
    }
  • 相关阅读:
    四则运算
    3.12----对potplayer的使用评价
    对软件工程的一点思考
    个人附加作业
    附加题
    个人最终总结
    结对编程总结
    修改后的四则运算
    阅读程序回答问题
    Visual studio 2013的安装和单元测试
  • 原文地址:https://www.cnblogs.com/zhendiao/p/14882885.html
Copyright © 2011-2022 走看看