在牛客面经上遇到的一个面试题。突然想尝试下
然后就开始做了
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>
执行之后打印的结果
总的来说就是打印的结果是构造方法->注解@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); } } }