【Spring源码】@Bean解析

在ConfigurationClassPostProcessor中,从BeanDefinationRegistry中取出所有的beanDefination,并循环每一个BD,如果bean类上存在@Component / @ComponentScan / @Import / @ImportResource 或者有@Bean的方法,就会对这些注解信息进行解析。

1. 解析@PropertySources注解,将指定的配置文件解析成配置信息

image

2. 解析@ComponentScan,会对扫描到的类进行递归解析。

image

3. 解析当前类的@Import注解

image

4. 获取有@Bean注解的方法,加到ConfigClass.beanMethods容器中

image
  1. 拿到该类中所有带有@Bean的方法
image
  1. 封装成BeanMethod对象
image

解析完所有的BD之后,会处理BeanMethod对象

image
image

解析每一个BeanMethod对象

image

针对@Bean注解的信息,创建BeanDefination,并注册到BeanDefinationRegistry

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
        ConfigurationClass configClass = beanMethod.getConfigurationClass();
        MethodMetadata metadata = beanMethod.getMetadata();
        String methodName = metadata.getMethodName();
        // @conditionnal注解,判断是否需要跳过
        // Do we need to mark the bean as skipped by its condition?
        if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
            configClass.skippedBeanMethods.add(methodName);
            return;
        }
        if (configClass.skippedBeanMethods.contains(methodName)) {
            return;
        }
        // 获取@Bean注解
        AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
        Assert.state(bean != null, "No @Bean annotation attributes");

        // Consider name and any aliases
        // 获取beanName,
        // 如果配置了多个name,第一个作为beanName,其他的作为别名
        // 如果一个都没配置,将方法名作为别名
        List<String> names = new ArrayList<>(Arrays.asList(bean.getStringArray("name")));
        String beanName = (!names.isEmpty() ? names.remove(0) : methodName);

        // 设置除第一个之外的其他name,作为别名
        // Register aliases even when overridden
        for (String alias : names) {
            this.registry.registerAlias(beanName, alias);
        }

        // Has this effectively been overridden before (e.g. via XML)?
        if (isOverriddenByExistingDefinition(beanMethod, beanName)) {
            if (beanName.equals(beanMethod.getConfigurationClass().getBeanName())) {
                throw new BeanDefinitionStoreException(beanMethod.getConfigurationClass().getResource().getDescription(),
                        beanName, "Bean name derived from @Bean method '" + beanMethod.getMetadata().getMethodName() +
                        "' clashes with bean name for containing configuration class; please make those names unique!");
            }
            return;
        }
            // 创建BeanDefination
        ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
        beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));

        if (metadata.isStatic()) {
            // static @Bean method
            if (configClass.getMetadata() instanceof StandardAnnotationMetadata) {
                beanDef.setBeanClass(((StandardAnnotationMetadata) configClass.getMetadata()).getIntrospectedClass());
            }
            else {
                beanDef.setBeanClassName(configClass.getMetadata().getClassName());
            }
            beanDef.setUniqueFactoryMethodName(methodName);
        }
        else {
            // instance @Bean method
            // 设置FactoryBeanName
            beanDef.setFactoryBeanName(configClass.getBeanName());
            // 设置FactoryMethod,那么实例化的时候会调用FactoryBeanName的bean的FactoryMethod来创建bean
            beanDef.setUniqueFactoryMethodName(methodName);
        }

        if (metadata instanceof StandardMethodMetadata) {
            beanDef.setResolvedFactoryMethod(((StandardMethodMetadata) metadata).getIntrospectedMethod());
        }

        beanDef.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);
        beanDef.setAttribute(org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
                SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);

        AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);

        Autowire autowire = bean.getEnum("autowire");
        if (autowire.isAutowire()) {
            beanDef.setAutowireMode(autowire.value());
        }

        boolean autowireCandidate = bean.getBoolean("autowireCandidate");
        if (!autowireCandidate) {
            beanDef.setAutowireCandidate(false);
        }
        // 设置initMethodName
        String initMethodName = bean.getString("initMethod");
        if (StringUtils.hasText(initMethodName)) {
            beanDef.setInitMethodName(initMethodName);
        }
        // 设置destroyMethodName
        String destroyMethodName = bean.getString("destroyMethod");
        beanDef.setDestroyMethodName(destroyMethodName);

        // Consider scoping
        // 设置Scoep作作用域属性
        ScopedProxyMode proxyMode = ScopedProxyMode.NO;
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
        if (attributes != null) {
            beanDef.setScope(attributes.getString("value"));
            proxyMode = attributes.getEnum("proxyMode");
            if (proxyMode == ScopedProxyMode.DEFAULT) {
                proxyMode = ScopedProxyMode.NO;
            }
        }

        // Replace the original bean definition with the target one, if necessary
        BeanDefinition beanDefToRegister = beanDef;
        if (proxyMode != ScopedProxyMode.NO) {
            BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy(
                    new BeanDefinitionHolder(beanDef, beanName), this.registry,
                    proxyMode == ScopedProxyMode.TARGET_CLASS);
            beanDefToRegister = new ConfigurationClassBeanDefinition(
                    (RootBeanDefinition) proxyDef.getBeanDefinition(), configClass, metadata);
        }

        if (logger.isTraceEnabled()) {
            logger.trace(String.format("Registering bean definition for @Bean method %s.%s()",
                    configClass.getMetadata().getClassName(), beanName));
        }
        // 注册BeanDefinition
        this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    }

除了对BeanDefinition的一些常用属性进行设置之外,最主要的就是设置BeanDefinition的FactoryBeanName和FactoryMethod,那么实例化的时候会调用FactoryBeanName对应的bean的FactoryMethod方法来创建bean

推荐阅读更多精彩内容