服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - spring Bean的初始化过程解析

spring Bean的初始化过程解析

2022-09-07 14:20morris131 Java教程

这篇文章主要介绍了spring Bean的初始化过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

spring Bean的初始化过程解析

AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

使用BeanPostProcessor收集带有注解的方法和属性,方便下面初始化时调用。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

?
1
2
3
4
5
6
7
8
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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<>();
        // 查找带有@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));
            }
        });
        // 查找带有@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

?
1
2
3
4
5
6
7
8
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    // 构造方法会注入@PostConstruct、@PreDestroy
    // 父类会查找带有@PostConstruct、@PreDestroy注解的方法
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    // 查找带有@Resource注解的属性和方法
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

AbstractAutowireCapableBeanFactory#populateBean

调用各个BeanPostProcessor.postProcessProperties对属性进行设置。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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的调用主要是反射进行属性的设置和方法的调用,如果属性是引用类型,将会触发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()完成了对象的初始化,下面将会调用对象的初始化方法完成最后的初始化过程。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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完成调用。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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不仅需要实现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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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

?
1
2
3
4
5
6
7
8
9
10
11
12
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

?
1
2
3
4
5
6
7
8
9
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

?
1
2
3
4
5
6
7
8
9
10
11
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // LifecycleMetadata缓存数据从何来?
    // 前面在调用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缓存数据从何来?前面在调用CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@Resource注解时,同时会调用
父类InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@PostConstruct注解。

而PostConstruct注解是在CommonAnnotationBeanPostProcessor的构造方法中指定的。

?
1
2
3
4
5
6
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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这三者要实现的功能都是一致的,都是在bean实例化并初始化完成之后进行调用。

具体使用如下:

InitBean.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

运行结果与源码分析的一致,先执行PostConstruct,再执行afterPropertiesSet,最后initMethod。

注意这三种初始化方法都不能带有参数。

到此这篇关于spring Bean的初始化过程的文章就介绍到这了,更多相关spring Bean初始化内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/u022812849/article/details/123394691

延伸 · 阅读

精彩推荐