spring?Bean的初始化過程解析
AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
使用BeanPostProcessor收集帶有注解的方法和屬性,方便下面初始化時調用。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof MergedBeanDefinitionPostProcessor) { MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp; bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName); } } }
這里的BeanPostProcessor主要有以下兩個:
- AutowiredAnnotationBeanPostProcessor:負責@Autowired、@Value
- CommonAnnotationBeanPostProcessor:負責@Resource、@PostConstruct、@PreDestroy
AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
AutowiredAnnotationBeanPostProcessor負責@Autowired、@Value注解的方法和屬性的收集。
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) { // autowiredAnnotationTypes是在構造方法中被初始化的 // autowiredAnnotationTypes @Autowired @Value if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 查找?guī)в蠤Autowired注解的屬性 ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // 查找?guī)в蠤Autowired注解的方法 ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); }
CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
CommonAnnotationBeanPostProcessor負責@Resource、@PostConstruct、@PreDestroy注解的方法和屬性的收集,收集過程與AutowiredAnnotationBeanPostProcessor的收集過程類似。
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { // 構造方法會注入@PostConstruct、@PreDestroy // 父類會查找?guī)в蠤PostConstruct、@PreDestroy注解的方法 super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); // 查找?guī)в蠤Resource注解的屬性和方法 InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null); metadata.checkConfigMembers(beanDefinition); }
AbstractAutowireCapableBeanFactory#populateBean
調用各個BeanPostProcessor.postProcessProperties對屬性進行設置。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { ... ... if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 調用各個BeanPostProcessor.postProcessProperties對屬性進行設置 /** * AutowiredAnnotationBeanPostProcessor處理@Autowired * CommonAnnotationBeanPostProcessor處理@Resource * * @see AutowiredAnnotationBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String) * @see org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String) */ PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); ... ... }
CommonAnnotationBeanPostProcessor#postProcessProperties
對帶有@Resource注解的屬性進行設置,對帶有@Resource注解的方法進行調用。
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 上面的方法postProcessMergedBeanDefinition向緩存中設置了@PostConstruct、@PreDestroy注解的方法,@Resource注解的屬性和方法 // 這里會從緩存中取出對這些屬性進行設置,方法進行調用 InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs); try { /** * @see org.springframework.beans.factory.annotation.InjectionMetadata#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues) */ metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex); } return pvs; }
AutowiredAnnotationBeanPostProcessor#postProcessProperties方法也是如此,對帶有@Autowired注解的屬性進行設置,對帶有@Autowired注解的方法進行調用。
InjectionMetadata#inject
org.springframework.beans.factory.annotation.InjectionMetadata#inject
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { /** * CommonAnnotationBeanPostProcessor注入的是InjectionMetadata.InjectedElement對象 * @see InjectedElement#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues) * * AutowiredAnnotationBeanPostProcessor注入的是AutowiredFieldElement和AutowiredMethodElement * @see AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues) * @see AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues) */ element.inject(target, beanName, pvs); } } }
InjectedElement的調用主要是反射進行屬性的設置和方法的調用,如果屬性是引用類型,將會觸發(fā)beanFactory.getBean()方法從Spring容器中獲取對象。
AbstractAutowireCapableBeanFactory#initializeBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
上面的populateBean()完成了對象的初始化,下面將會調用對象的初始化方法完成最后的初始化過程。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // 調用aware方法 // BeanNameAware/BeanClassLoaderAware/BeanFactoryAware對應的setXxx方法 invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // 處理EnvironmentAware/EmbeddedValueResolverAware/ResourceLoaderAware/ // ApplicationEventPublisherAware/MessageSourceAware/ApplicationContextAware // 處理@PostConstruct wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // InitializingBean.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()) { // AOP代理入口 wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }
AbstractAutowireCapableBeanFactory#invokeAwareMethods
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
這里只完成了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的初始化方法調用,還有部分aware接口將通過下面的BeanPostProcessor完成調用。
private void invokeAwareMethods(String beanName, Object bean) { if (bean instanceof Aware) { if (bean instanceof BeanNameAware) { ((BeanNameAware) bean).setBeanName(beanName); } if (bean instanceof BeanClassLoaderAware) { ClassLoader bcl = getBeanClassLoader(); if (bcl != null) { ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl); } } if (bean instanceof BeanFactoryAware) { ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this); } } }
AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { /** * ApplicationContextAwareProcessor調用EnvironmentAware/EmbeddedValueResolverAware/ResourceLoaderAware/ * ApplicationEventPublisherAware/MessageSourceAware/ApplicationContextAware * * ImportAwareBeanPostProcessor調用ImportAware(Bean不僅需要實現(xiàn)ImportAware接口,還要有@Import注解) * InitDestroyAnnotationBeanPostProcessor 處理@PostConstruct * * @see org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) * @see org.springframework.context.annotation.ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) * @see org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) */ Object current = processor.postProcessBeforeInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
ApplicationContextAwareProcessor#postProcessBeforeInitialization
ApplicationContextAwareProcessor負責EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware接口的調用。
org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){ return bean; } AccessControlContext acc = null; if (System.getSecurityManager() != null) { acc = this.applicationContext.getBeanFactory().getAccessControlContext(); } if (acc != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { invokeAwareInterfaces(bean); } return bean; } private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } }
ImportAwareBeanPostProcessor#postProcessBeforeInitialization
ImportAwareBeanPostProcessor主要負責ImportAware接口的調用。
ImportAware的具體使用如下:
ImportAwareBean.java
package com.morris.spring.entity.imports; import org.springframework.context.annotation.ImportAware; import org.springframework.core.type.AnnotationMetadata; public class ImportAwareBean implements ImportAware { @Override public void setImportMetadata(AnnotationMetadata importMetadata) { // 在這里可以拿到注入ImportAwareBean的類ImportConfig上的注解@Transactional System.out.println(importMetadata.getAnnotationTypes()); } }
ImportConfig.java
package com.morris.spring.config; import com.morris.spring.entity.imports.ImportAwareBean; import org.springframework.context.annotation.Import; import org.springframework.transaction.annotation.Transactional; @Transactional @Import(ImportAwareBean.class) public class ImportConfig { }
org.springframework.context.annotation.ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization
public Object postProcessBeforeInitialization(Object bean, String beanName) { if (bean instanceof ImportAware) { ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class); // bean必須通過@Import注解注入進來,importingClass才會有值 AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName()); if (importingClass != null) { ((ImportAware) bean).setImportMetadata(importingClass); } } return bean; }
InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // LifecycleMetadata緩存數(shù)據(jù)從何來? // 前面在調用CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@Resource注解時,同時會調用 // 父類InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@PostConstruct注解 // 負責@PostConstruct方法的調用 LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass()); try { metadata.invokeInitMethods(bean, beanName); } catch (InvocationTargetException ex) { throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException()); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Failed to invoke init method", ex); } return bean; }
LifecycleMetadata緩存數(shù)據(jù)從何來?前面在調用CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@Resource注解時,同時會調用
父類InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@PostConstruct注解。
而PostConstruct注解是在CommonAnnotationBeanPostProcessor的構造方法中指定的。
public CommonAnnotationBeanPostProcessor() { setOrder(Ordered.LOWEST_PRECEDENCE - 3); setInitAnnotationType(PostConstruct.class); setDestroyAnnotationType(PreDestroy.class); ignoreResourceType("javax.xml.ws.WebServiceContext"); }
AbstractAutowireCapableBeanFactory#invokeInitMethods
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods
protected void invokeInitMethods(String beanName, 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 { // 調用InitializingBean.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)) { // 調用init-method invokeCustomInitMethod(beanName, bean, mbd); } } }
@PostConstruct、afterPropertiesSet、init-method
@PostConstruct、InitializingBean.afterPropertiesSet、init-method這三者要實現(xiàn)的功能都是一致的,都是在bean實例化并初始化完成之后進行調用。
具體使用如下:
InitBean.java
package com.morris.spring.entity; import org.springframework.beans.factory.InitializingBean; import javax.annotation.PostConstruct; public class InitBean implements InitializingBean { @PostConstruct public void postConstruct() { System.out.println("PostConstruct"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet"); public void init(){ System.out.println("init"); }
InitDemo.java
package com.morris.spring.demo.annotation; import com.morris.spring.entity.InitBean; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class InitDemo { @Bean(initMethod = "init") public InitBean initBean() { return new InitBean(); } public static void main(String[] args) { new AnnotationConfigApplicationContext(InitDemo.class); }
運行結果如下:
PostConstruct
afterPropertiesSet
init
運行結果與源碼分析的一致,先執(zhí)行PostConstruct,再執(zhí)行afterPropertiesSet,最后initMethod。
注意這三種初始化方法都不能帶有參數(shù)。
到此這篇關于spring Bean的初始化過程的文章就介紹到這了,更多相關spring Bean初始化內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java web將數(shù)據(jù)導出為pdf格式文件代碼片段
這篇文章主要為大家詳細介紹了java web將數(shù)據(jù)導出為pdf格式文件代碼片段,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-01-01spring配置文件中util:properties和context:property-placeholder用法
這篇文章主要介紹了spring配置文件中util:properties和context:property-placeholder用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo
這篇文章主要為大家介紹了flowable動態(tài)創(chuàng)建多級流程模板實現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05springboot?jpa?實現(xiàn)返回結果自定義查詢
這篇文章主要介紹了springboot?jpa?實現(xiàn)返回結果自定義查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02