详解Spring的CreateBean方法

2023-11-07

在AbstractBeanFactory类的doGetBean()中,都是调用AbstractAutowireCapableBeanFactory类的createBean()来创建Bean实例,该方法参数如下:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

第一个参数为beanName,第二个为beanName对应的RootBeanDefinition,第三个参数为构造器的参数列表,实例化的时候需要参数列表推断使用哪一个构造器来进行实例化

1、加载beanClass

在扫描指定包下面的class文件生成BeanDefinition的时候,beanDefinition中的beanClass属性暂时存放的是类的名称(全称),而不是加载后的Class对象,但是在实例化Bean对象之前,JVM需要加载将class文件加载进来,并用beanDefinition中的beanClass存储Class对象

RootBeanDefinition mbdToUse = mbd;
// 马上就要实例化Bean了,确保beanClass被加载了
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    mbdToUse = new RootBeanDefinition(mbd);
    mbdToUse.setBeanClass(resolvedClass);
}

下面看resolveBeanClass(mbd, beanName)是如何获取Class对象的,如果该RootBeanDefinition对应的Class对象已经加载,则直接返回该对象,否则调用doResolveBeanClass(mbd, typesToMatch)方法来加载Class对象

protected Class<?> resolveBeanClass(RootBeanDefinition mbd, String beanName, Class<?>... typesToMatch)
    throws CannotLoadBeanClassException {

    try {
        // 如果beanClass被加载了
        if (mbd.hasBeanClass()) {
            return mbd.getBeanClass();
        }
        ……		
            // 如果beanClass没有被加载
            return doResolveBeanClass(mbd, typesToMatch);
    }
}

看doResolveBeanClass是如何实现的

private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
    throws ClassNotFoundException {

    // 获取类加载器
    ClassLoader beanClassLoader = getBeanClassLoader();
    ClassLoader dynamicLoader = beanClassLoader;
    boolean freshResolve = false;
    if (!ObjectUtils.isEmpty(typesToMatch)) {
        // When just doing type checks (i.e. not creating an actual instance yet),
        // use the specified temporary class loader (e.g. in a weaving scenario).
        ClassLoader tempClassLoader = getTempClassLoader();
        if (tempClassLoader != null) {
            dynamicLoader = tempClassLoader;
            freshResolve = true;
            if (tempClassLoader instanceof DecoratingClassLoader) {
                DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
                for (Class<?> typeToMatch : typesToMatch) {
                    dcl.excludeClass(typeToMatch.getName());
                }
            }
        }
    }
  • 首先获取类加载器,getBeanClassLoader()会调用ClassUtils类中的getDefaultClassLoader()获取类加载器,获取类加载的代码如下:

    首先获取当前线程指定上下文加载器,可以在Spring容器启动之前,设置当前线程(主线程)上下文的类加载器

    Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
    

    如果没有指定,则获取当前类ClassUtils的类加载器,如果当前类是通过bootstrap加载的,则获取系统类加载器

    public static ClassLoader getDefaultClassLoader() {
        ClassLoader cl = null;
    
        // 优先获取线程中的类加载器
        cl = Thread.currentThread().getContextClassLoader();
    
        // 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器
        if (cl == null) {
            // No thread context class loader -> use class loader of this class.
            cl = ClassUtils.class.getClassLoader();
            if (cl == null) {
                // getClassLoader() returning null indicates the bootstrap ClassLoader
                // 假如ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器
                cl = ClassLoader.getSystemClassLoader();
            }
        }
        return cl;
    }
    
  • 判断beanClassName是否是EL表达式

    getBeanClassName()方法返回的可能是类加载的名字,也可能只是类名,如果beanClass是一个Spring的EL表达式,则evaluateBeanDefinitionString可以将其解析,返回一个Class对象或类名

    String className = mbd.getBeanClassName();
    if (className != null) {
        // 解析Spring表达式,有可能直接返回了一个Class对象
        Object evaluated = evaluateBeanDefinitionString(className, mbd);
        if (!className.equals(evaluated)) {
            // A dynamically resolved expression, supported as of 4.2...
            if (evaluated instanceof Class) {
                return (Class<?>) evaluated;
            }
            else if (evaluated instanceof String) {
                className = (String) evaluated;
                freshResolve = true;
            }
        }
        if (freshResolve) {
            if (dynamicLoader != null) {
               return dynamicLoader.loadClass(className);
            }
            return ClassUtils.forName(className, dynamicLoader);
        }
    }
    
  • 解析生成beanClass

    如果前面的条件都无法得到Class对象,则调用RootBeanDefinition的resolveBeanClass方法

    @Nullable
    private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
        throws ClassNotFoundException {
        ……
        return mbd.resolveBeanClass(beanClassLoader);
    }
    

    resolveBeanClass()中调用 ClassUtils.forName生成对应Class对象,然后将Class对象存储在RootBeanDefinition的beanClass属性中

    public Class<?> resolveBeanClass(@Nullable ClassLoader classLoader) throws ClassNotFoundException {
        String className = getBeanClassName();
        if (className == null) {
            return null;
        }
        Class<?> resolvedClass = ClassUtils.forName(className, classLoader);
        this.beanClass = resolvedClass;
        return resolvedClass;
    }
    

2、实例化前

在实例化前操作的前面,会调用prepareMethodOverrides()处理带有@Lookup注解的方法,然后再进行实例化前的操作

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    ……
    mbdToUse.prepareMethodOverrides();
    ……
}

在对Bean进行实例化之前,调用resolveBeforeInstantiation()执行初始化前的操作,如果初始化前的操作直接就生成了Bean对象,则直接返回,没必要再执行后面的实例化操作

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    ……
    // 实例化前
    Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    if (bean != null) {
        return bean;
    }
    ……
}

resolveBeforeInstantiation()中,hasInstantiationAwareBeanPostProcessors()会判断当前Spring容器的Bean中是否有实现了InstantiationAwareBeanPostProcessor接口的Bean

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        // synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}
  • 判断是否有Bean实现了InstantiationAwareBeanPostProcessor接口

    protected boolean hasInstantiationAwareBeanPostProcessors() {
        return !getBeanPostProcessorCache().instantiationAware.isEmpty();
    }
    

    在讲清楚InstantiationAwareBeanPostProcessor之前,需要先了解一下AbstractBeanFactory中的静态内部类BeanPostProcessorCache,源码如下:

    static class BeanPostProcessorCache {
    
        final List<InstantiationAwareBeanPostProcessor> instantiationAware = new ArrayList<>();
    
        final List<SmartInstantiationAwareBeanPostProcessor> smartInstantiationAware = new ArrayList<>();
    
        final List<DestructionAwareBeanPostProcessor> destructionAware = new ArrayList<>();
    
        final List<MergedBeanDefinitionPostProcessor> mergedDefinition = new ArrayList<>();
    }
    

    BeanPostProcessCache中分别缓存实现了InstantiationAwareBeanPostProcessor、SmartInstantiationAwareBeanPostProcessor、DestructionAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor接口的Bean对象,而这四个接口都继承自BeanPostProcessor接口,BeanPostProcessor接口定义了postProcessBeforeInitialization()和postProcessAfterInitialization两个方法,即初始化前和初始化需要调用的方法,在这两个方法的基础上,上述四个接口也定义各自的方法,源码如下

    public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
        // 实例化前调用
        default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            return null;
        }
        
        // 实例化后调用
        default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            return true;
        }
        
        //属性填充
        default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {
    
            return null;
        }
    }
    
    public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
        default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
            return null;
        }
        default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {
    
            return null;
        }
        default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    
    public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
        void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
        default boolean requiresDestruction(Object bean) {
            return true;
        }
    }
    
    public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
        void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
        default void resetBeanDefinition(String beanName) {
        }
    
    }
    

    下面介绍getBeanPostProcessorCache()方法的实现

    AbstractBeanFactory类的beanPostProcessorCache属性是BeanPostProcessorCache类的实例,缓存各种实现了BeanPostPocessor的Bean对象,如果当前缓存为空,就从beanPostProcessors中取出所有实现了BeanPostProcessor接口的Bean实例,然后将它们进行细分之后,进行缓存

    BeanPostProcessorCache getBeanPostProcessorCache() {
        BeanPostProcessorCache bpCache = this.beanPostProcessorCache;
        if (bpCache == null) {
            bpCache = new BeanPostProcessorCache();
            for (BeanPostProcessor bp : this.beanPostProcessors) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    bpCache.instantiationAware.add((InstantiationAwareBeanPostProcessor) bp);
                    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                        bpCache.smartInstantiationAware.add((SmartInstantiationAwareBeanPostProcessor) bp);
                    }
                }
                if (bp instanceof DestructionAwareBeanPostProcessor) {
                    bpCache.destructionAware.add((DestructionAwareBeanPostProcessor) bp);
                }
                if (bp instanceof MergedBeanDefinitionPostProcessor) {
                    bpCache.mergedDefinition.add((MergedBeanDefinitionPostProcessor) bp);
                }
            }
            this.beanPostProcessorCache = bpCache;
        }
        return bpCache;
    }
    
  • 调用实例化前方法

    上面已经详细介绍了beanPostProcessorCache,现在再回到resolveBeforeInstantiation()方法,如果有实现了InstantiationAwareBeanPostProcessor接口的Bean,调用determineTargetType()推断出BeanDefinition所代表的类型

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        Class<?> targetType = determineTargetType(beanName, mbd);
        if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
                bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
        }
    }
    

    然后调用applyBeanPostProcessorsBeforeInstantiation()执行实例化前方法,beanPostProcessorCache可能有多个实现了InstantiationAwareBeanPostProcessor接口的Bean对象,则遍历调用这些对象的postProcessBeforeInstantiation()方法,如果某个对象调用该方法时返回了一个对象,则直接返回该对象

    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
       for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
          Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
          if (result != null) {
             return result;
          }
       }
       return null;
    }
    
  • 如果调用实例化前方法产生了对象,则调用初始化后方法

    在调用实例化前方法时,如果返回了不为空的对象,则调用applyBeanPostProcessorsAfterInitialization(),遍历所有实现了BeanPostProcessor接口的Bean对象,调用它们的postProcessAfterInitialization()初始化后方法,如果调用某个对象的初始化方法返回了null,则直接返回

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
    
        Object result = existingBean;
    
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
    

3、实例化

经历了实例化前操作,如果返回的对象不是null,则直接将返回的对象作为Bean实例,如果返回的对象等于null,则调用doCreateBean()方法创建Bean实例

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

doCreateBean()中调用createBeanInstance()来完成实例化

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 创建Bean实例
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
}

具体的实例化过程涉及到根据@Bean注解实例化、以及构造方法推断等,后续构造推断再细讲实例化的过程

4、实例化后

在doCreateBean()中调用createBeanInstance()完成Bean的实例化以后,还需要进行实例化后的一系列的操作

  • BeanDefinition后置处理

    完成实例化之后,遍历BeanPostProcessorCache中缓存的实现了MergedBeanDefinitionPostProcessor接口的Bean对象,然后调用对象的postProcessMergedBeanDefinition()方法,对合并的BeanDefinition进行操作,包括设置初始化方法名、属性赋值等等操作

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        ……
            synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        } 
        ……
    }
    
    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
            processor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
    
  • 属性填充

    执行完BeanDefinition的后置处理后,将进行属性填充,而属性填充又涉及到一系列的动作

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        ……
        // 属性填充
        populateBean(beanName, mbd, instanceWrapper);
        ……
    }
    

    调用实例化后方法:

    这个地方同实例化前操作相似,不过这里调用的是实现了InstantiationAwareBeanPostProcessor接口的Bean对象的postProcessAfterInstantiation()实例化后方法

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        ……
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return;
                }
            }
        }
    }
    

    属性填充:

    AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor都继承了InstantiationAwareBeanPostProcessor接口,而这两个类会在postProcessProperties()方法中解决@Autowired和@Resource的属性注入,代码中的pvs得到的是在BeanDefinition后置处理中设置属性值,如果设置了属性值,AutowiredAnnotationBeanPostProcessor将不在处理这些属性,直接返回

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        ……
            boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                // 这里会调用AutowiredAnnotationBeanPostProcessor的postProcessProperties()方法,会直接给对象中的属性赋值
                // AutowiredAnnotationBeanPostProcessor内部并不会处理pvs,直接返回了
                PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                }
                pvs = pvsToUse;
            }
        }
    }
    
  • 初始化

    属性填充完成之后,进行初始化的操作

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
        ……
        // 初始化
    	exposedObject = initializeBean(beanName, exposedObject, mbd);
        ……
    }
    

    调用Aware方法:

    在进行初始化的时候,首先判断当前Bean实现了哪些Aware接口,然后设置对应的属性

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        ……
        invokeAwareMethods(beanName, bean);
        ……
    }
    
    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);
            }
        }
    }
    

    调用初始化前方法:

    Aware方法调用完成之后,调用初始化前方法,执行所有BeanPostProcessor的postProcessBeforeInitialization()初始化前方法,如果某个Bean对象调用该方法返回null,则直接返回,不再执行后面Bean对象的方法

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        ……
        if (mbd == null || !mbd.isSynthetic()) {
            // 初始化前
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        ……
    }
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {
    
        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
    

    调用初始化方法:

    初始化的过程中,会判断当前Bean实例是否实现了InitializingBean接口,如果实现了该接口,则会调用Bean对象的afterPropertiesSet()方法,如果在BeanDifinition的后置处理中设置了初始化方法名并且该对象中有此方法,放回通过反射调用指定的初始化方法

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        ……
        // 初始化
        invokeInitMethods(beanName, wrappedBean, mbd);
        ……
    }
    protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    
        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("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)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }
    

    调用初始化后:

    初始化完成之后,调用初始化后方法,执行所有BeanPostProcessor的postProcessAfterInitialization()初始化后方法,如果某个Bean对象调用该方法返回null,则直接返回,不再执行后面Bean对象的方法

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
        ……
        // 初始化后
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        ……
    }
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
    
        Object result = existingBean;
    
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessAfterInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
    
  • 注册Bean销毁逻辑

    在后续Bean销毁会讲到注册Bean销毁逻辑以及Bean的销毁

至此,一个完整的Bean对象创建完成,这一片篇文章主要讲述的是Bean的生命周期,而里面涉及到的更详细的推断构造方法、依赖注入和解决循环依赖这些核心的实现将在后续章节详细介绍

5、总结

创建一个Bean的大概过程/Bean生命周期:

1、调用AbstractBeanFactory.resolveBeanClass()加载类

2、调用InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation() ,实例化前方法

3、调用AbstractAutowireCapableBeanFactory.createBeanInstance() 通过推断构造,完成实例化

4、调用MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),完成合并的BeanDefinition的后置处理(设置初始化方法名、属性等)

5、调用InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),执行实例化后的逻辑

6、调用InstantiationAwareBeanPostProcessor.postProcessProperties(),完成属性填充

7、调用AbstractAutowireCapableBeanFactory.invokeAwareMethods(),完成相关属性设置

8、调用BeanPostProcessor.postProcessBeforeInitialization(),完成初始化前操作,这一步包含了很多的属性设置,postProcessBeforeInitialization()的实现类有很多,都是在这一步完成操作

9、调用InitializingBean.afterPropertiesSet(),以及初始化方法

10、调用BeanPostProcessor.postProcessAfterInitialization()初始化后方法

6、@PostConstruct和@PreDestroy方法执行

定义了这两个注解的方法都会在执行初始化前操作中完成缓存同时执行@PostConstruct方法,Spring中默认有很多实现了BeanPostProcessor的接口的类,它们在Spring启动的过程中,调用调用postProcessBeforeInitialization()

其中这两个注解方法的缓存以及@PostConstruct注解方法的执行都是在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization()中

首先调用findLifecycleMetadata()方法,找到所有当前类以及其父类中定义@PostConstruct和@PreDestroy的方法,然后调用@PostConstruct定义的方法(初始化方法)

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    //调用初始化方法
    metadata.invokeInitMethods(bean, beanName);
    return bean;
}

findLifecycleMetadata()的具体实现如下,lifecycleMetadataCache是@PostConstruct和@PreDestroy的方法的缓存池,其中KEY为beanClass,VALUE为LifecycleMetadata实例对象,而LifecycleMetadata中存放了benaClass对应的@PostConstruct和@PreDestroy的方法,先根据benaClass从缓存中取,如果没有再扫描获取这些方法

private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
    if (this.lifecycleMetadataCache == null) {
        // Happens after deserialization, during destruction...
        return buildLifecycleMetadata(clazz);
    }
    // Quick check on the concurrent map first, with minimal locking.
    LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
    if (metadata == null) {
        synchronized (this.lifecycleMetadataCache) {
            metadata = this.lifecycleMetadataCache.get(clazz);
            if (metadata == null) {
                metadata = buildLifecycleMetadata(clazz);
                this.lifecycleMetadataCache.put(clazz, metadata);
            }
            return metadata;
        }
    }
    return metadata;
}

// LifecycleMetadata 结构如下
private class LifecycleMetadata {

    private final Class<?> targetClass;

    private final Collection<LifecycleElement> initMethods;

    private final Collection<LifecycleElement> destroyMethods;

    @Nullable
    private volatile Set<LifecycleElement> checkedInitMethods;

    @Nullable
    private volatile Set<LifecycleElement> checkedDestroyMethods;
    ……
}
// 具体的方法存放在LifecycleElement实例中
private static class LifecycleElement {

    private final Method method;

    private final String identifier;
    ……
}

如果当前lifecycleMetadataCache缓存中找不到对应的方法,则调用buildLifecycleMetadata(clazz)来扫描beanClass中所有的方法以及父类中的方法,判断是否有方法添加了@PostConstruct和@PreDestroy

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    List<LifecycleElement> initMethods = new ArrayList<>();
    List<LifecycleElement> destroyMethods = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<LifecycleElement> currInitMethods = new ArrayList<>();
        final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                LifecycleElement element = new LifecycleElement(method);
                currInitMethods.add(element);
            }
            if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                currDestroyMethods.add(new LifecycleElement(method));
            }
        });

        // 父类的在前面,执行初始化方法时,先执行父类的初始化方法
        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        // 先遍历当前类的方法,再遍历父类的方法
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
            new LifecycleMetadata(clazz, initMethods, destroyMethods));
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解Spring的CreateBean方法 的相关文章

  • 光学标记阅读器的开源库[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我想要一个用于光学标记读取 OMR 的开源库 有这样的库吗 我想在我的 java 应用程序中使用这个库 zxing 可能对你有用 http
  • Spring Rest-API - 403 禁止错误响应

    我是 Spring 新手 我正在编写 REST API 我收到 403 删除 放置禁止错误 以下是我正在处理的示例 RequestMapping value noteId method RequestMethod PUT public Re
  • 如何在 Java 中根据 XSD 1.1 验证 XML?

    在 Java 中根据 XML Schema 1 1 验证 XML 文件的最佳方法是什么 我从中获取了代码tutorial http www ibm com developerworks xml library x javaxmlvalida
  • Android - 内容值覆盖现有行

    我正在尝试使用插入值ContentValues 我已将 5 个值插入到 5 列中 运行应用程序后 我只有最后一组值的行ContentValues 前四组未插入 ContentValues cv new ContentValues cv pu
  • 使用 spring security 找不到 AuthenticationProvider

    我一直在尝试使用 x509 证书通过 LDAP 对用户进行身份验证 但似乎无法正常工作 我声明了一个身份验证提供程序 但仍然抛出错误 提示没有提供程序 这是我的调试输出 INFO Initiating Jersey application
  • 寻找 WebElements,最佳实践

    在我们当前的自动化 使用 Selenium WebDriver Java 中 我们使用 FindBy very广泛地 例如 FindBy css a name bcrumb protected List
  • 如何使用java避免Mysql数据库中的“数据因列被截断”?

    在我的 Java 程序中 Hibernate Bean 类定义一列 例如 TimtableVO java Column name REPEAT DAYS private WeekdayType repeatDays hear Weekday
  • java中main的返回类型

    我想知道为什么java中main方法只有void返回类型 public static void main String args 为什么main方法除了void之外没有其他返回类型 Thanks 简短的回答是 因为这就是语言规范 http
  • MAC OS 的 java.awt.Robot 类中出现无头环境错误

    我正在尝试使用 JavaFX 应用程序捕获屏幕截图Robot class 这是我在我的应用程序中使用的代码 Rectangle screenBounds new Rectangle Screen getPrimary getBounds g
  • 如何加快 jar 签名者的速度?

    我使用 ant 来签署我的 jars 以进行网络启动部署 Ant signjar 在 Web 启动签名时非常慢 如何加快签名过程 我找到了一种可能的解决方案 早些时候 在构建脚本 ant signjar 中 按顺序调用所有 jar 我们使用
  • 使用 eclipse 配置mockito 时出现问题。给出错误:java.lang.verifyError

    当我将我的mockito库添加到类路径中 并使用一个简单的mockito示例进行测试时 我尝试使用模拟对象为函数add返回错误的值 我得到java lang verifyerror 以下是用于测试的代码 后面是 logcat Test pu
  • Ubuntu 的打包 - Web 应用程序

    Web 应用程序没有与 C 或类似文件不同的 make 文件 但是 它需要放置在特定的目录中 例如 var www 我是 Linux 打包新手 所以我的问题是 如何将我的应用程序打包到 deb 中 以便在安装时将其放入 etc myprog
  • 创建一个 int 类型的随机数组。爪哇

    我需要创建一个随机的 int 数组 并按我自己的类对其进行排序 这是我制作数组的地方 public class MyProgram9 public static void main String args int list new int
  • 这个finally子句包含close()调用的原因是什么

    我正在学习在线java课程 使用 Java 编程简介 http math hws edu javanotes index html 在 I O 章节中 引入了以下代码 顺便说一下 在本程序的末尾 您将发现我们第一个有用的 try 语句中的
  • 使用 Mockitos 传递参数化输入

    我正在使用 Mockito 进行单元测试 我想知道是否可以使用 Junit 测试中的方式发送参数化输入参数 e g InjectMocks MockClass mockClass new MockClass Test public void
  • Java中如何限制文件大小

    我正在我的应用程序中创建一个文件 并继续向该文件中写入一些内容 但是当我的文件达到一定大小 比如说 100 行 后 我想删除第一行并将新行写入底部 要求是我的文件应该受到限制 但它应该保留我写入文件的最新内容 请告诉我在Java中是否可行
  • Google App Engine数据存储区字符串编码问题

    你好 我正在使用 Google App Engine 进行一个项目 并且需要存储一些字符串 我正在使用 Java 和JDOHelper getPersistenceManagerFactory transactions optional 在
  • 如何检测java控制台中而不是GUI中的箭头键? [复制]

    这个问题在这里已经有答案了 我正在编写一个应用程序 我需要检测其中的箭头键 C 有getch 函数 我们想要获取输入 然后添加对 ASCII 值的检查 我们如何检测输入箭头键 谢谢 我写了一个Java类原始控制台输入 http www so
  • JBoss 5 截断 base64 cookie 字符串的尾部 =

    从 JBoss 4 升级到 JBoss 5 后 我注意到最烦人的回归 它截断 base64 cookie 值的尾部等号 我花了很长时间才明白问题不是我的代码而是 JBoss 的 我用 google 搜索了一下 发现这是一个已知的问题issu
  • 使用 Tomcat 和 gradle 进行休眠

    免责声明 我是 Java 新手 我正在尝试使用 Tomcat 和 Gradle 设置 Hibernate 构建运行正确 但看起来像persistence xml文件未被读取 我的项目结构如下 build gradle src main ja

随机推荐

  • yolox小计

    1 环境配置 1 1 没有什么用的试错 activate D conda envs pytorch pip3 install U pip pip3 install r requirements txt 报错 解决办法 python m en
  • XNA是什么?

    Software will be the single most important force in digital entertainment over the next decade XNA underscores Microsoft
  • 虚幻4学习笔记(9)基础概念、常用快捷键汇总、蓝图概念

    虚幻4学习笔记 基础概念 常用快捷键汇总 中英文命名注意事项 帧和秒的概念 带星号文件的意思 编译的作用 实例和原素材 情景关联 蓝图概念 函数概念 宏的概念 宏与蓝图的区别 函数 事件的区别 变量的概念 面向对象思想 B站UP谌嘉诚课程
  • springMVC @ModelAttribute学习

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 转自 http hbiao68 iteye com blog 1948380 ModelAttribute 绑定请求参数到命令对象 ModelAttribute一个具有如下
  • 前后端分离部署方式

    转自https www cnblogs com moveofgod p 12363544 html 写得简洁明了 例如 vue 这种前后端分离的框架如何部署 1 前后端一起部署 前端打包成静态文件后 copy 到后端项目中 然后部署后端项目
  • GO语言实战要点摘录

    1 变量的声明与定义 1 var t T 通常用于零值初始化 非零值初始化通常采用短变量声明 初始化的方式 type user struct name string age int 用右侧的指定的类型初始化变量 每行初始化一个变量 以逗号结
  • numpy和pandas简单快速入门

    由于部分代码需要和数据文件配合 将项目和文件个人的GitHub 地址 https github com 1769172502 machine learning 关于numpy参考菜鸟地址 http www runoob com numpy
  • 使用QProcess调用外部程序

    在实际的项目开发中往往会有调用外部程序的需求 例如 主程序中添加调用记事本的快捷方式等 QProcess调用接口介绍 QProcess是Qt专门用于外部程序启动并与之通信的类 启动外部程序主要分为两种方式 一体式 将随主程序的退出而退出 v
  • 如何解决Dev-c++无法调试或者无法性能分析的问题

    无法调试 1 打开Dev c 2 点击屏幕顶部的 工具 3 点击 编译选项 4 点击 代码生成 优化 5 点击 连接器 6 将 产生调试信息 改为 yes 7 点击 确定 无法性能分析 1 打开Dev c 2 点击屏幕顶部的 工具 3 点击
  • uniapp调试 手机上没有信任本计算机的授权,请在手机上信任该授权

    真机运行失败 失败原因 手机上没有信任本计算机的授权 请在手机上信任该授权 HBUILDER 手机调试 提示没有授权 其实就是usb调试权限 刷这样才能用pc操作手机进行安装app等操作 这个时候可以 断开手机和电脑的连接 然后重新连接 跳
  • SQLyog ERROR 1045 : Access denied for user ‘root’@‘localhost’ (using password: YES)

    Linux和MySQL小白遇到的一些问题 在window中使用SQLyog远程连接虚拟机中Linux CentOs7 中的MySQL数据库 问题描述及解决方法1 连接时报错ERROR 1045 Access denied for user
  • uniapp实现用户登录

    store js文件 login vue页面
  • html语言左对齐是什么,html - 如何左对齐标签?

    我试图左对齐标签保持输入字段右对齐没有成功 我能够对齐标签或输入字段 但不能同时使用它们 我已经尝试了很多东西 但没有奏效html 如何左对齐标签 HTML Info Cod Name Phone Address CSS form styl
  • halcon识别斜着的车牌

    对于倾斜的车牌 我们必须用仿射变换 将车牌弄正 再进行识别 如图 halcon代码 read image Image666 C Users Administrator Desktop 666 jpg decompose3 Image666
  • C/C++经典项目:用C++制作在线考试系统(附源码)

    在线考试是指通过操作计算机在网络上进行考试整个过程的一种考试形式 脱离了纸质媒体 也可以说成是通过网络媒体进行的考试 是现如今比较常用的一种考试形式 用C 编写的在线考试系统 Access MSSQL数据库可选 从权限操作来看 包含学生 教
  • java如何使用代码求两个list集合的差集呢?

    转自 java如何使用代码求两个list集合的差集呢 下文笔者讲述求list集合的差集的方法简介说明 如下所示 差集 用一个集合减去一个集合得到的集合 我们称之为 差集 实现思路 使用stream流中的filter方法对集合 进行 不包含关
  • C#编程,字符串与字符、字符串与字节的转化方法

    1 string 转换成 Char string ss abcdefg char cc ss ToCharArray 2 Char 转换成string string s new string cc 3 byte 与 string 之间的装换
  • 字典树(Trie树) Java实现源码参考

    定义 字典树 又称为单词查找树 Tire数 是一种树形结构 它是一种哈希树的变种 用于保存大量的字符串 它的优点是 利用字符串的公共前缀来节约存储空间 字典树结构对应的Java源码 public class Trie char val bo
  • mysql-基础篇

    Mysql 基础篇 MySQL概述 数据库相关概念 名称 全称 简称 数据库 存储数据的仓库 数据是有组织的进行存储 DataBase DB 数据库管理系统 操纵和管理数据库的大型软件 DataBase Management System
  • 详解Spring的CreateBean方法

    在AbstractBeanFactory类的doGetBean 中 都是调用AbstractAutowireCapableBeanFactory类的createBean 来创建Bean实例 该方法参数如下 protected Object