0
点赞
收藏
分享

微信扫一扫

解析Spring中@Bean的实现原理

M4Y 2022-03-23 阅读 76
spring

https://blog.csdn.net/CSDN_WYL2016/article/details/108223930

文章目录

介绍

在SpringBoot的项目中,经常会使用@Bean这样的注解,这个是定义在方法上的注解,也可以用来替代以前通过XML注入Bean的方式,但又与@Configuration或者@Component这样正常的注入方式不太一样,本文将会分析具体的实现原理。

如何扫描到@Bean注解的

refresh入口

我们知道refresh是Spring容器启动的主流程方法,就从这开始看起。

    @Override
    public void refresh() throws BeansException, IllegalStateException {
        //。。。省略部分代码
        //这个方法会处理bean中的各种注解,其中包含了@Bean的解析
        invokeBeanFactoryPostProcessors(beanFactory);
        //。。。省略部分代码
                
    }
12345678
    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
​
        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }
12345678910
    public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
        //。。。省略部分代码
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //。。。省略部分代码
    }
123456

BeanFactoryPostProcessor

这里利用BeanFactoryPostProcessor扩展处理

    private static void invokeBeanDefinitionRegistryPostProcessors(
            Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
        
        for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanDefinitionRegistry(registry);
        }
    }
1234567
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        int registryId = System.identityHashCode(registry);
        if (this.registriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
        }
        if (this.factoriesPostProcessed.contains(registryId)) {
            throw new IllegalStateException(
                    "postProcessBeanFactory already called on this post-processor against " + registry);
        }
        this.registriesPostProcessed.add(registryId);
​
        processConfigBeanDefinitions(registry);
    }
123456789101112131415

核心解析流程

大概分析这部分处理流程

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        //先获取容器中所有的BeanDefinition对象,这部分对象会更早的被容器加载到,利用ConfigurationClassPostProcessor这个类完成的,我在之前的博文中有介绍过
        String[] candidateNames = registry.getBeanDefinitionNames();
        
        //遍历所有beanName
        for (String beanName : candidateNames) {
            //通过beanName,获取BeanDefinition对象
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
                }
            }
            //这个判断会找当前BeanDefinition的方法中是否有@Bean的注解,如果有就返回true
            /**
            // Finally, let's look for @Bean methods...
            try {
                    return metadata.hasAnnotatedMethods(Bean.class.getName());
                }
                catch (Throwable ex) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
                    }
                    return false;
            }
            */
            
            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                //封装成BeanDefinitionHolder对象,并添加到list集合中
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
​
        // Return immediately if no @Configuration classes were found
        if (configCandidates.isEmpty()) {
            return;
        }
​
        // Sort by previously determined @Order value, if applicable
        //有@Order注解的完成排序
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return Integer.compare(i1, i2);
        });
​
        // Detect any custom bean name generation strategy supplied through the enclosing application context
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            sbr = (SingletonBeanRegistry) registry;
            if (!this.localBeanNameGeneratorSet) {
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                        AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
                if (generator != null) {
                    this.componentScanBeanNameGenerator = generator;
                    this.importBeanNameGenerator = generator;
                }
            }
        }
​
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
​
        // Parse each @Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this.componentScanBeanNameGenerator, registry);
​
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
            //核心解析,看后面的分析
            parser.parse(candidates);
            parser.validate();
            
            //从刚刚解析的过程中获取ConfigurationClass集合,这个类里面又包含了BeanMethod对象集合,而这个对象封装了@Bean的方法
            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            configClasses.removeAll(alreadyParsed);
​
            // Read the model and create bean definitions based on its content
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                        registry, this.sourceExtractor, this.resourceLoader, this.environment,
                        this.importBeanNameGenerator, parser.getImportRegistry());
            }
            //加载bean对象到BeanDefinitions中,看后面分析。
            this.reader.loadBeanDefinitions(configClasses);
            alreadyParsed.addAll(configClasses);
​
            candidates.clear();
            if (registry.getBeanDefinitionCount() > candidateNames.length) {
                String[] newCandidateNames = registry.getBeanDefinitionNames();
                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
                Set<String> alreadyParsedClasses = new HashSet<>();
                for (ConfigurationClass configurationClass : alreadyParsed) {
                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
                }
                for (String candidateName : newCandidateNames) {
                    if (!oldCandidateNames.contains(candidateName)) {
                        BeanDefinition bd = registry.getBeanDefinition(candidateName);
                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                            candidates.add(new BeanDefinitionHolder(bd, candidateName));
                        }
                    }
                }
                candidateNames = newCandidateNames;
            }
        }
        while (!candidates.isEmpty());
​
        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
        }
​
        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
            // Clear cache in externally provided MetadataReaderFactory; this is a no-op
            // for a shared cache since it'll be cleared by the ApplicationContext.
            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
        }
    }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124

parser.parse(candidates)方法最终会执行到下面这个方法

    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {
        //。。。省略部分代码
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            //主要看这边,把有@Bean注解的封装成BeanMethod对象,并添加到ConfigurationClass类中的一个set集合属性中
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }
        //。。。省略部分代码
​
    }
1234567891011

loadBeanDefinitions

    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        for (ConfigurationClass configClass : configurationModel) {
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }
123456

loadBeanDefinitionsForConfigurationClass

    private void loadBeanDefinitionsForConfigurationClass(
            ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
​
        if (trackedConditionEvaluator.shouldSkip(configClass)) {
            String beanName = configClass.getBeanName();
            if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
                this.registry.removeBeanDefinition(beanName);
            }
            this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
            return;
        }
​
        if (configClass.isImported()) {
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }
        //遍历ConfigurationClass中的beanMethods集合。
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }
​
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }
1234567891011121314151617181920212223

loadBeanDefinitionsForBeanMethod

    private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
        ConfigurationClass configClass = beanMethod.getConfigurationClass();
        MethodMetadata metadata = beanMethod.getMetadata();
        //。。。省略部分代码
        ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass, metadata);
        //。。。省略部分代码
        // instance @Bean method
        //设置BeanDefinition中的factoryBeanName属性值为当前class对象的beanName
        beanDef.setFactoryBeanName(configClass.getBeanName());
        //设置BeanDefinition中的factoryMethodName属性值为当前class对象中@Bean方法的methodName
        beanDef.setUniqueFactoryMethodName(methodName);
        //。。。省略部分代码
        BeanDefinition beanDefToRegister = beanDef;
        //。。。省略部分代码
        //把封装后的BeanDefinition注册到beanDefinitionMap和beanDefinitionNames容器中,spring实例化过程会遍历这个容器中的bean
        //beanDefinitionMap中key是@Bean的方法名,value是@Bean所属对象的BeanDefinition
        //beanDefinitionNames是list集合,存放的是@Bean的方法名
        this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    }
12345678910111213141516171819

流程梳理

分析到这对有@Bean注解的方法,Spring的处理策略就大致了解了。 1、先找到有@Configuration或者@Component注解的bean对象。 2、检查bean对象中是否有@Bean注解的方法,如果存在封装成BeanMethod对象,并添加到一个set集合中。 3、遍历集合,然后拿到bean对象对应的BeanDefinition,设置factoryMethodName属性为@Bean方法的先关信息,这就相当于在当前bean对应的BeanDefinition对象中添加了一个标识,用于识别是否有@Bean的方法。 4、最后把以@Bean注解的方法名为key,BeanDefinition为value,添加到beanDefinitionMap容器中,把@Bean注解的方法名添加到beanDefinitionNames容器中,一个map集合,一个list集合。

如何注入@Bean实例的

处理factoryMethodName属性

    @Override
    public void preInstantiateSingletons() throws BeansException {
        //。。。省略部分代码
        List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
​
        //遍历beanDefinitionNames集合,包含了之前添加进去的@Bean注释的方法名
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) {
                            getBean(beanName);
                        }
                    }
                }
                else {
                    //获取bean对象
                    getBean(beanName);
                }
            }
        }
        //。。。省略部分代码
    }
123456789101112131415161718192021222324252627282930313233343536
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
1234

getBean会执行到doGetBean方法

    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
​
                //。。。省略部分代码
                //根据beanName获取BeanDefinition对象,之前解析过可以从一个名为beanDefinitionMap的map容器中获取,value就是bean对应的BeanDefinition对象。
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
                
                //。。。省略部分代码
                // Create bean instance.
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            //创建bean对象,beanName为方法名,mbd为bean对应的BeanDefinition对象
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                //。。。省略部分代码
    }
12345678910111213141516171819202122232425262728

实例化

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        //。。。省略部分代码
        //判断当前BeanDefinition是否有factoryMethodName属性,之前分析过有@Bean注解的会设置这个属性
        if (mbd.getFactoryMethodName() != null) {
            //利用反射调用@Bean注释的方法
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }
        //。。。省略部分代码
    }
123456789
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
            @Nullable Object factoryBean, final Method factoryMethod, Object... args) {
            //。。。省略部分代码
            try {
                //factoryMethod即@Bean注释的方法,利用反射完成调用并返回方法中的对象
                Object result = factoryMethod.invoke(factoryBean, args);
                if (result == null) {
                    result = new NullBean();
                }
                return result;
            }
            //。。。省略部分代码
}
12345678910111213

总结

后半部分也比较简单,先遍历beanDefinitionNames这个list集合,依次处理,再通过beanDefinitionMap找到bean对应的BeanDefinition对象,最后在实例化对象的时候,判断当前BeanDefinition对象中factoryMethodName属性是否有值,如果有则通过反射调用@Bean注释的方法拿到bean的实例,这就实现将@Bean注解的方法注入到容器中了,name为方法名,value为方法返回值。

举报

相关推荐

0 条评论