Spring Bean生命周期
本文基于图灵课堂周瑜老师的讲解整理,包括spring bean加载的过程,主要是扫描BeanDefinition以及初始化非懒加载单例Bean两部分,源码取自SpringFramework 5.3.22
1. Bean扫描
本小节介绍的是Spring从给定的扫描位置扫描到待加载的Bean,生成BeanDefinitionMap的过程
SpringBoot启动过程中使用的ApplicationContext是AnnotationConfigApplicationContext,而它初始化的时候会顺带初始化两个BeanDefinitionReader:AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner,前者是可以直接通过给定的class注册Bean,后者则可以扫描给定目录下所有的目标Bean,下面着重介绍后者扫描Bean组件的过程。
ClassPathBeanDefinitionScanner扫描的入口是public int scan(String... basePackages),而真正做事情的是protected Set doScan(String... basePackages)方法,代码如下:- /**<br> * Perform a scan within the specified base packages,<br> * returning the registered bean definitions.<br> * <p>This method does <i>not</i> register an annotation config processor<br> * but rather leaves this up to the caller.<br> * @param basePackages the packages to check for annotated classes<br> * @return set of beans registered if any for tooling registration purposes (never {@code null})<br> */<br>protected Set<BeanDefinitionHolder> doScan(String... basePackages) {<br> Assert.notEmpty(basePackages, "At least one base package must be specified");<br> Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();<br> for (String basePackage : basePackages) {<br> // 找到basePackage下的所有候选组件,这里只是把classname赋值给了BeanDefinition<br> Set<BeanDefinition> candidates = findCandidateComponents(basePackage);<br> for (BeanDefinition candidate : candidates) {<br> // 获取组件的scope,默认是单例的<br> ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);<br> candidate.setScope(scopeMetadata.getScopeName());<br> // 获取beanname<br> String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);<br> if (candidate instanceof AbstractBeanDefinition) {<br> postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);<br> }<br> // 处理通用的注解<br> if (candidate instanceof AnnotatedBeanDefinition) {<br> AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);<br> }<br> // 最后再对BeanDefinition做检查,看下是否有重名的<br> if (checkCandidate(beanName, candidate)) {<br> BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);<br> definitionHolder =<br> AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);<br> beanDefinitions.add(definitionHolder);<br> registerBeanDefinition(definitionHolder, this.registry);<br> }<br> }<br> }<br> return beanDefinitions;<br> }
复制代码 下面将以上部分代码展开去讲
1.1 扫描包下面的所有组件
即对应findCandidateComponents方法的操作,该方法如下:- /**<br> * Scan the class path for candidate components.<br> * @param basePackage the package to check for annotated classes<br> * @return a corresponding Set of autodetected bean definitions<br> */<br> public Set<BeanDefinition> findCandidateComponents(String basePackage) {<br> if (this.componentsIndex != null && indexSupportsIncludeFilters()) {<br> return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);<br> }<br> else {<br> return scanCandidateComponents(basePackage);<br> }<br> }
复制代码
- 首先来判断是否有对应的索引,即看componentsIndex是否有值,它加载的是META-INF/spring.components中的信息,内容格式如下:
- com.sgw.demo=org.springframework.stereotype.Component
复制代码 之后,就加载这里的Bean组件,不去做扫描,对于项目过于庞大,扫描耗费时间的情况,可以考虑这种方案,个人感觉对于现在的微服务架构,这种应该没太多实际场景
- 如果没有索引,即进入真正的扫描流程scanCandidateComponents,代码如下:
- private Set<BeanDefinition> scanCandidateComponents(String basePackage) {<br> Set<BeanDefinition> candidates = new LinkedHashSet<>();<br> try {<br> // 根据传入的包名,得到对应的classpath中的路径<br> String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +<br> resolveBasePackage(basePackage) + '/' + this.resourcePattern;<br> // 获取该路径下的所有class文件<br> Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);<br> boolean traceEnabled = logger.isTraceEnabled();<br> boolean debugEnabled = logger.isDebugEnabled();<br> for (Resource resource : resources) {<br> if (traceEnabled) {<br> logger.trace("Scanning " + resource);<br> }<br> try {<br> // 使用ASM读取class文件<br> MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);<br> // 判断是否是要扫描的组件<br> if (isCandidateComponent(metadataReader)) {<br> ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);<br> // 设置resource文件<br> sbd.setSource(resource);<br> // 判断扫描到的组件是否是正常的类(是不是独立的,检查是不是接口、抽象类(带LookUp注解的除外))<br> if (isCandidateComponent(sbd)) {<br> if (debugEnabled) {<br> logger.debug("Identified candidate component class: " + resource);<br> }<br> candidates.add(sbd);<br> }<br> else {<br> if (debugEnabled) {<br> logger.debug("Ignored because not a concrete top-level class: " + resource);<br> }<br> }<br> }<br> else {<br> if (traceEnabled) {<br> logger.trace("Ignored because not matching any filter: " + resource);<br> }<br> }<br> }<br> catch (FileNotFoundException ex) {<br> if (traceEnabled) {<br> logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());<br> }<br> }<br> catch (Throwable ex) {<br> throw new BeanDefinitionStoreException(<br> "Failed to read candidate component class: " + resource, ex);<br> }<br> }<br> }<br> catch (IOException ex) {<br> throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);<br> }<br> return candidates;<br>}
复制代码
- 根据传入的包名,得到对应的classpath中的路径
前面加上classpath*:前缀,后面加上**/*.class,同时把包名中的.替换成/
- 基于第一步拼接的搜索路径,得到下面所有的class文件,并以Resource数组的形式返回
- 遍历得到的Resource数组,使用ASM读取class文件
有个问题是为什么这里已经取得了类名,不直接用jdk的classloader加载进去呢,原因是效率问题,把扫描到的类都加载上去第一没必要,第二浪费时间
- 判断是否是要扫描的组件
这里是基于exclude以及include两类filter以及conditional注解来做的,看下具体代码实现- /**<br> * Determine whether the given class does not match any exclude filter<br> * and does match at least one include filter.<br> * @param metadataReader the ASM ClassReader for the class<br> * @return whether the class qualifies as a candidate component<br> */<br> protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {<br> for (TypeFilter tf : this.excludeFilters) {<br> if (tf.match(metadataReader, getMetadataReaderFactory())) {<br> return false;<br> }<br> }<br> for (TypeFilter tf : this.includeFilters) {<br> if (tf.match(metadataReader, getMetadataReaderFactory())) {<br> return isConditionMatch(metadataReader);<br> }<br> }<br> return false;<br> }
复制代码 这些是从ComponentScan这个注解中解析出来的,是includeFilters和excludeFilters这俩属性,平时我们什么都不配置,默认扫描的是@Component @Repository @Service @Controller 这些注解,它们是会默认出现在includeFilters中的。
如果命中了includefilter,接下来检查是否有conditional注解,如果有,则判断是否满足条件。
- 判断扫描到的组件是否是正常的类
这里是有一套逻辑,因为一些内部类、抽象类、接口编译之后也会生成class文件,而这些文件到这一步是没有被过滤的,这里涉及到一个概念,说类是不是独立的,注释中是这么说的:
Determine whether the underlying class is independent, i.e. whether it is a top-level class or a nested class (static inner class) that can be constructed independently of an enclosing class.
即不依赖其他类也能正常被构建,因为后面扫描完成,有一个很重要的步骤,是实例化,而那些非静态的内部类、接口、抽象类是不能被实例化的,故这里排除在外。
1.2 依次处理扫描到的组件
- 获取组件的scope
通过解析scope注解获取,默认是单例属性
- 获取BeanDefinition的名称,即BeanName,首先从注解中取,如果没有就基于类名生成一个,用到了Introspector.decapitalize(shortClassName)方法
- 处理AbstractBeanDefinition ,设置BeanDefinition中的默认值
- 解析bean的一些注解,并记录到BeanDefinition中,包括Lazy、Primary、DependsOn、Role、Description
- 之后,再次检查对应的BeanDefinition是否已经被加载了,出现这种情况可能是同一个类被扫描到了两次,这里就是检查如果是有两个同名的,只能允许它们是同一个类被扫描了两次,如果是其他情况,即两个bean同名,那么直接报错
- 都检查通过之后,注册该BeanDefinition,等待之后的处理
2. 非懒加载单例Bean的创建
本小节介绍在扫描完BeanDefinition之后的,在初始化的时候做的事情,对于每一个扫描到的BeanDefinition,合并成RootBeanDefinition,之后调用getSingleton,如果是单例非懒加载Bean,就实例化、初始化Bean,加载到单例池中。
这里是在ApplicitionContext的refresh()方法中调用的,其中有beanFactory.preInstantiateSingletons();这么一步,即初始化所有的非懒加载的单例Bean,具体实现如下:- public void preInstantiateSingletons() throws BeansException {<br> if (logger.isTraceEnabled()) {<br> logger.trace("Pre-instantiating singletons in " + this);<br> }<br><br> // Iterate over a copy to allow for init methods which in turn register new bean definitions.<br> // While this may not be part of the regular factory bootstrap, it does otherwise work fine.<br> List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);<br><br> // Trigger initialization of all non-lazy singleton beans...<br> for (String beanName : beanNames) {<br> // 因为之前BeanDefinition存在继承的概念,这里是合并子BeanDefinition和父BeanDefinition<br> RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);<br> if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {<br> // 非懒加载单例bean<br> if (isFactoryBean(beanName)) {<br> // 处理工厂Bean<br> Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);<br> if (bean instanceof FactoryBean) {<br> FactoryBean<?> factory = (FactoryBean<?>) bean;<br> boolean isEagerInit;<br> if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {<br> isEagerInit = AccessController.doPrivileged(<br> (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,<br> getAccessControlContext());<br> }<br> else {<br> isEagerInit = (factory instanceof SmartFactoryBean &&<br> ((SmartFactoryBean<?>) factory).isEagerInit());<br> }<br> if (isEagerInit) {<br> getBean(beanName);<br> }<br> }<br> }<br> else {<br> // 初始化Bean<br> getBean(beanName);<br> }<br> }<br> }<br><br> // Trigger post-initialization callback for all applicable beans...<br> for (String beanName : beanNames) {<br> Object singletonInstance = getSingleton(beanName);<br> if (singletonInstance instanceof SmartInitializingSingleton) {<br> StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")<br> .tag("beanName", beanName);<br> SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;<br> if (System.getSecurityManager() != null) {<br> AccessController.doPrivileged((PrivilegedAction<Object>) () -> {<br> smartSingleton.afterSingletonsInstantiated();<br> return null;<br> }, getAccessControlContext());<br> }<br> else {<br> smartSingleton.afterSingletonsInstantiated();<br> }<br> smartInitialize.end();<br> }<br> }<br> }
复制代码 之后的核心实现在getBean(beanName)的doGetBean();方法中,如下:- /**<br> * Return an instance, which may be shared or independent, of the specified bean.<br> * @param name the name of the bean to retrieve<br> * @param requiredType the required type of the bean to retrieve<br> * @param args arguments to use when creating a bean instance using explicit arguments<br> * (only applied when creating a new instance as opposed to retrieving an existing one)<br> * @param typeCheckOnly whether the instance is obtained for a type check,<br> * not for actual use<br> * @return an instance of the bean<br> * @throws BeansException if the bean could not be created<br> */<br>@SuppressWarnings("unchecked")<br>protected <T> T doGetBean(<br> String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)<br> throws BeansException {<br> // 处理BeanName,如果是前面加了&符号,去除之,如果是别名,得到其正式的名称<br> String beanName = transformedBeanName(name);<br> Object beanInstance;<br><br> // 这里先试着获取下单例池中有没有对应的单例对象,如果有的话,就直接返回<br> // Eagerly check singleton cache for manually registered singletons.<br> Object sharedInstance = getSingleton(beanName);<br> if (sharedInstance != null && args == null) {<br> if (logger.isTraceEnabled()) {<br> if (isSingletonCurrentlyInCreation(beanName)) {<br> logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +<br> "' that is not fully initialized yet - a consequence of a circular reference");<br> }<br> else {<br> logger.trace("Returning cached instance of singleton bean '" + beanName + "'");<br> }<br> }<br> beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);<br> }<br><br> else {<br> // Fail if we're already creating this bean instance:<br> // We're assumably within a circular reference.<br> if (isPrototypeCurrentlyInCreation(beanName)) {<br> throw new BeanCurrentlyInCreationException(beanName);<br> }<br><br> // 如果本bean工厂不存在传进来的BeanName,并且存在父工厂,则到父工厂中寻找<br> // Check if bean definition exists in this factory.<br> BeanFactory parentBeanFactory = getParentBeanFactory();<br> if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {<br> // Not found -> check parent.<br> String nameToLookup = originalBeanName(name);<br> if (parentBeanFactory instanceof AbstractBeanFactory) {<br> return ((AbstractBeanFactory) parentBeanFactory).doGetBean(<br> nameToLookup, requiredType, args, typeCheckOnly);<br> }<br> else if (args != null) {<br> // Delegation to parent with explicit args.<br> return (T) parentBeanFactory.getBean(nameToLookup, args);<br> }<br> else if (requiredType != null) {<br> // No args -> delegate to standard getBean method.<br> return parentBeanFactory.getBean(nameToLookup, requiredType);<br> }<br> else {<br> return (T) parentBeanFactory.getBean(nameToLookup);<br> }<br> }<br><br> if (!typeCheckOnly) {<br> markBeanAsCreated(beanName);<br> }<br><br> StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")<br> .tag("beanName", name);<br> try {<br> if (requiredType != null) {<br> beanCreation.tag("beanType", requiredType::toString);<br> }<br> // 取合并之后的rootBeanDefinition<br> RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);<br> checkMergedBeanDefinition(mbd, beanName, args);<br><br> // 如果有被dependsOn注解修饰,优先初始化dependsOn中的bean<br> // Guarantee initialization of beans that the current bean depends on.<br> String[] dependsOn = mbd.getDependsOn();<br> if (dependsOn != null) {<br> for (String dep : dependsOn) {<br> if (isDependent(beanName, dep)) {<br> throw new BeanCreationException(mbd.getResourceDescription(), beanName,<br> "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");<br> }<br> registerDependentBean(dep, beanName);<br> try {<br> getBean(dep);<br> }<br> catch (NoSuchBeanDefinitionException ex) {<br> throw new BeanCreationException(mbd.getResourceDescription(), beanName,<br> "'" + beanName + "' depends on missing bean '" + dep + "'", ex);<br> }<br> }<br> }<br><br> // 之后基于不同的scope来创建bean<br> // Create bean instance.<br> if (mbd.isSingleton()) {<br> sharedInstance = getSingleton(beanName, () -> {<br> try {<br> return createBean(beanName, mbd, args);<br> }<br> catch (BeansException ex) {<br> // Explicitly remove instance from singleton cache: It might have been put there<br> // eagerly by the creation process, to allow for circular reference resolution.<br> // Also remove any beans that received a temporary reference to the bean.<br> destroySingleton(beanName);<br> throw ex;<br> }<br> });<br> beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);<br> }<br><br> else if (mbd.isPrototype()) {<br> // It's a prototype -> create a new instance.<br> Object prototypeInstance = null;<br> try {<br> beforePrototypeCreation(beanName);<br> prototypeInstance = createBean(beanName, mbd, args);<br> }<br> finally {<br> afterPrototypeCreation(beanName);<br> }<br> beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);<br> }<br><br> else {<br> String scopeName = mbd.getScope();<br> if (!StringUtils.hasLength(scopeName)) {<br> throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");<br> }<br> Scope scope = this.scopes.get(scopeName);<br> if (scope == null) {<br> throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");<br> }<br> try {<br> Object scopedInstance = scope.get(beanName, () -> {<br> beforePrototypeCreation(beanName);<br> try {<br> return createBean(beanName, mbd, args);<br> }<br> finally {<br> afterPrototypeCreation(beanName);<br> }<br> });<br> beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);<br> }<br> catch (IllegalStateException ex) {<br> throw new ScopeNotActiveException(beanName, scopeName, ex);<br> }<br> }<br> }<br> catch (BeansException ex) {<br> beanCreation.tag("exception", ex.getClass().toString());<br> beanCreation.tag("message", String.valueOf(ex.getMessage()));<br> cleanupAfterBeanCreationFailure(beanName);<br> throw ex;<br> }<br> finally {<br> beanCreation.end();<br> }<br> }<br><br> return adaptBeanInstance(name, beanInstance, requiredType);<br>}
复制代码
- 处理BeanName
如果是前面加了&符号,去除之,如果是别名,得到其正式的名称
- 先试着获取下单例池中有没有对应的单例对象,如果有的话,就直接返回
- 如果本bean工厂不存在传进来的BeanName,并且存在父工厂,则到父工厂中寻找
- 如果有被dependsOn注解修饰,优先初始化dependsOn中的bean
- 之后基于不同的scope来创建bean
这里的scope主要有以下几种
- prototype
- requestScope
即同一个request中的bean要保持一致
- sessionScope
即同一个session中的bean要保持一致
之后的两个是通过设置request和session中的属性来实现的
以上的情况,需要真正创建bean的时候,就会落到AbstractAutowireCapableBeanFactory中实现的createBean中,
首先加载BeanClass,resolveBeanClass(mbd, beanName),把bean加载到对应的classLoader中。
实例化
这里是bean构造的第一个扩展点,如下:- try {<br> // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.<br> Object bean = resolveBeforeInstantiation(beanName, mbdToUse);<br> if (bean != null) {<br> return bean;<br> }<br>}<br>catch (Throwable ex) {<br> throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,<br> "BeanPostProcessor before instantiation of bean failed", ex);<br>}
复制代码 这里是实例化之前调用的接口,注释中看到的就是给BeanPostProcessor接口的实现类一个构造代理bean的机会,实现偷天幻日的机会。具体如下:- /**<br> * Apply before-instantiation post-processors, resolving whether there is a<br> * before-instantiation shortcut for the specified bean.<br> * @param beanName the name of the bean<br> * @param mbd the bean definition for the bean<br> * @return the shortcut-determined bean instance, or {@code null} if none<br> */<br>@Nullable<br>protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {<br> Object bean = null;<br> if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {<br> // Make sure bean class is actually resolved at this point.<br> if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {<br> Class<?> targetType = determineTargetType(beanName, mbd);<br> if (targetType != null) {<br> bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);<br> if (bean != null) {<br> bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);<br> }<br> }<br> }<br> mbd.beforeInstantiationResolved = (bean != null);<br> }<br> return bean;<br>}
复制代码 首先会看,是否已经实例化了,如果没有实例化,就依次调用已经实现了的postProcessBeforeInstantiation接口,Spring中的AOP即利用的这里的扩展点,将命中切面表达式的Bean替换成对应的代理类,AOP实现的接口是AbstractAutoProxyCreator。
之后确认是走正常的Bean初始化流程,即进入doCreateBean方法,具体实现如下,这里实现了bean生命周期中的多个重要的扩展点,包括依赖注入、初始化前后、实例化后、初始化等:- /**<br> * Actually create the specified bean. Pre-creation processing has already happened<br> * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.<br> * <p>Differentiates between default bean instantiation, use of a<br> * factory method, and autowiring a constructor.<br> * @param beanName the name of the bean<br> * @param mbd the merged bean definition for the bean<br> * @param args explicit arguments to use for constructor or factory method invocation<br> * @return a new instance of the bean<br> * @throws BeanCreationException if the bean could not be created<br> * @see #instantiateBean<br> * @see #instantiateUsingFactoryMethod<br> * @see #autowireConstructor<br> */<br>protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)<br> throws BeanCreationException {<br><br> // Instantiate the bean.<br> BeanWrapper instanceWrapper = null;<br> if (mbd.isSingleton()) {<br> instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);<br> }<br> if (instanceWrapper == null) {<br> instanceWrapper = createBeanInstance(beanName, mbd, args);<br> }<br> Object bean = instanceWrapper.getWrappedInstance();<br> Class<?> beanType = instanceWrapper.getWrappedClass();<br> if (beanType != NullBean.class) {<br> mbd.resolvedTargetType = beanType;<br> }<br><br> // 调用MergedBeanDefinitionPostProcessor中的postProcessMergedBeanDefinition<br> // Allow post-processors to modify the merged bean definition.<br> synchronized (mbd.postProcessingLock) {<br> if (!mbd.postProcessed) {<br> try {<br> applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);<br> }<br> catch (Throwable ex) {<br> throw new BeanCreationException(mbd.getResourceDescription(), beanName,<br> "Post-processing of merged bean definition failed", ex);<br> }<br> mbd.postProcessed = true;<br> }<br> }<br><br> // Eagerly cache singletons to be able to resolve circular references<br> // even when triggered by lifecycle interfaces like BeanFactoryAware.<br> boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&<br> isSingletonCurrentlyInCreation(beanName));<br> if (earlySingletonExposure) {<br> if (logger.isTraceEnabled()) {<br> logger.trace("Eagerly caching bean '" + beanName +<br> "' to allow for resolving potential circular references");<br> }<br> addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));<br> }<br><br> // Initialize the bean instance.<br> Object exposedObject = bean;<br> try {<br> populateBean(beanName, mbd, instanceWrapper);<br> exposedObject = initializeBean(beanName, exposedObject, mbd);<br> }<br> catch (Throwable ex) {<br> if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {<br> throw (BeanCreationException) ex;<br> }<br> else {<br> throw new BeanCreationException(<br> mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);<br> }<br> }<br><br> if (earlySingletonExposure) {<br> Object earlySingletonReference = getSingleton(beanName, false);<br> if (earlySingletonReference != null) {<br> if (exposedObject == bean) {<br> exposedObject = earlySingletonReference;<br> }<br> else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {<br> String[] dependentBeans = getDependentBeans(beanName);<br> Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);<br> for (String dependentBean : dependentBeans) {<br> if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {<br> actualDependentBeans.add(dependentBean);<br> }<br> }<br> if (!actualDependentBeans.isEmpty()) {<br> throw new BeanCurrentlyInCreationException(beanName,<br> "Bean with name '" + beanName + "' has been injected into other beans [" +<br> StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +<br> "] in its raw version as part of a circular reference, but has eventually been " +<br> "wrapped. This means that said other beans do not use the final version of the " +<br> "bean. This is often the result of over-eager type matching - consider using " +<br> "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");<br> }<br> }<br> }<br> }<br><br> // Register bean as disposable.<br> try {<br> registerDisposableBeanIfNecessary(beanName, bean, mbd);<br> }<br> catch (BeanDefinitionValidationException ex) {<br> throw new BeanCreationException(<br> mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);<br> }<br><br> return exposedObject;<br>}
复制代码 包含的扩展点
- 调用MergedBeanDefinitionPostProcessor中的postProcessMergedBeanDefinition
这里校验一些关于BeanDefinition的数据,同时也可以做些改动
CommonAnnotationBeanPostProcessor、AutowiredAnnotationBeanPostProcessor都实现了这个扩展点,这里是做一些注解的前置校验的工作
- 调用InstantiationAwareBeanPostProcessor中的postProcessAfterInstantiation实例化之后的扩展点
- // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the<br>// state of the bean before properties are set. This can be used, for example,<br>// to support styles of field injection.
复制代码
- 做Spring自带的依赖注入
- 调用InstantiationAwareBeanPostProcessor的postProcessProperties以及postProcessPropertyValues(废弃)接口做依赖注入
- 调用setBeanName、setBeanClassLoader、setBeanFactory
- 调用BeanPostProcessor中的postProcessBeforeInitialization接口,初始化前的扩展点
- 调用InitializingBean中的afterPropertiesSet接口
- 调用初始化方法
- 调用BeanPostProcessor中的postProcessAfterInitialization接口,初始化后的扩展点
- 初始化结束
-
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |