SpringIoc源码(七)- ApplicationContext(三)- refresh(prepareBeanFactory)

目录

prepareBeanFactory

1)、设置BeanFactory类加载器

2)、设置Spring Expression解析器

StandardBeanExpressionResolver

3)、ResourceEditorRegistrar

4)、ApplicationContextAwareProcessor

5)、ignoreDependencyInterface

6)、registerResolvableDependency

7)、ApplicationListenerDetector

8)、LOAD_TIME_WEAVER_BEAN_NAME

1)、containsBean

BeanFactoryUtils.transformedBeanName

containsSingleton

containsBeanDefinition

2)、添加织入相关处理

9)、Environment相关注成Bean


prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // Tell the internal bean factory to use the context's class loader etc.
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // Configure the bean factory with context callbacks.
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // Register early post-processor for detecting inner beans as ApplicationListeners.
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // Detect a LoadTimeWeaver and prepare for weaving, if found.
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // Set a temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // Register default environment beans.
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

1)、设置BeanFactory类加载器

beanFactory.setBeanClassLoader(getClassLoader());

如果为null,则从当前线程获取:

Thread.currentThread().getContextClassLoader();

2)、设置Spring Expression解析器

设置后BeanFactory则拥有了解析Spring Expression的能力,这个我们在项目中某个类,实现BeanFactoryAware其实是完全可以使用的,之前没有注意。下面分析

beanFactory.setBeanExpressionResolver(new 
    StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

StandardBeanExpressionResolver

public class StandardBeanExpressionResolver implements BeanExpressionResolver {
    /** Default expression prefix: "#{". */
    public static final String DEFAULT_EXPRESSION_PREFIX = "#{";

    /** Default expression suffix: "}". */
    public static final String DEFAULT_EXPRESSION_SUFFIX = "}";


    private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;

    private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;

    private ExpressionParser expressionParser;

    private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);

    private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);

    private final ParserContext beanExpressionParserContext = new ParserContext() {
        @Override
        public boolean isTemplate() {
            return true;
        }
        @Override
        public String getExpressionPrefix() {
            return expressionPrefix;
        }
        @Override
        public String getExpressionSuffix() {
            return expressionSuffix;
        }
    };

    public StandardBeanExpressionResolver() {
        this.expressionParser = new SpelExpressionParser();
    }

    public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
        this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
    }


    /**
     * Set the prefix that an expression string starts with.
     * The default is "#{".
     * @see #DEFAULT_EXPRESSION_PREFIX
     */
    public void setExpressionPrefix(String expressionPrefix) {
        this.expressionPrefix = expressionPrefix;
    }

    @Override
    @Nullable
    public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
        if (!StringUtils.hasLength(value)) {
            return value;
        }
        try {
            Expression expr = this.expressionCache.get(value);
            if (expr == null) {
                expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
                this.expressionCache.put(value, expr);
            }
            StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
            if (sec == null) {
                sec = new StandardEvaluationContext(evalContext);
                sec.addPropertyAccessor(new BeanExpressionContextAccessor());
                sec.addPropertyAccessor(new BeanFactoryAccessor());
                sec.addPropertyAccessor(new MapAccessor());
                sec.addPropertyAccessor(new EnvironmentAccessor());
                sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
                sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
                ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
                if (conversionService != null) {
                    sec.setTypeConverter(new StandardTypeConverter(conversionService));
                }
                customizeEvaluationContext(sec);
                this.evaluationCache.put(evalContext, sec);
            }
            return expr.getValue(sec);
        }
        catch (Throwable ex) {
            throw new BeanExpressionException("Expression parsing failed", ex);
        }
    }
}

其实现了BeanExpressionResolver接口,就一个接口方法,解析当前的字符串:

Object evaluate(@Nullable String value, BeanExpressionContext evalContext) 
    throws BeansException;

Spring Expression比如@Value注解,比如@Value("#{'kevin.demo'}")则需要改解析器进行解析,所以会有DEFAULT_EXPRESSION_PREFIX和DEFAULT_EXPRESSION_SUFFIX进行处理。在有参获取无参构造都会默认初始化SpelExpressionParserParserContext进行解析的时候需要。并且实现了evaluate方法,则拥有解析的能力了,更多的东西后面专门分析吧。

3)、ResourceEditorRegistrar

beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, 
    getEnvironment()));
public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
    private final PropertyResolver propertyResolver;

    private final ResourceLoader resourceLoader;

    public ResourceEditorRegistrar(ResourceLoader resourceLoader, PropertyResolver propertyResolver) {
        this.resourceLoader = resourceLoader;
        this.propertyResolver = propertyResolver;
    }
    // 后续调用该方法后就拥有了解析File、PathURL等能力了
    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
        ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
        doRegisterEditor(registry, Resource.class, baseEditor);
        doRegisterEditor(registry, ContextResource.class, baseEditor);
        doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
        doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
        doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
        doRegisterEditor(registry, Path.class, new PathEditor(baseEditor));
        doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
        doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));

        ClassLoader classLoader = this.resourceLoader.getClassLoader();
        doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
        doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
        doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));

        if (this.resourceLoader instanceof ResourcePatternResolver) {
            doRegisterEditor(registry, Resource[].class,
                    new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
        }
    }

    private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
        if (registry instanceof PropertyEditorRegistrySupport) {
            ((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
        }
        else {
            registry.registerCustomEditor(requiredType, editor);
        }
    }
}

    构造函数初始化了解析器和类加载器,但是后续调用了registerCustomEditors方法,初始化ResourceEditor添加了很多的类型,则就拥有了解析File、URL、Path等的能力了。这个我们在项目中某个类,实现BeanFactoryAware其实是完全可以使用的,之前没有注意。

4)、ApplicationContextAwareProcessor

    非常重要的BeanPostProcessor子类,初始化并且将当前的Processor注册到BeanFactory的beanPostProcessors中,后续为每个实现了EnvironmentAwareEmbeddedValueResolverAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAware或者ApplicationContextAware的子类回调该方法,设置属性,或者回调方法。调用postProcessBeforeInitialization方法,后续分析。

class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;

    private final StringValueResolver embeddedValueResolver;

    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new 
            EmbeddedValueResolver(applicationContext.getBeanFactory());
    }
}

5)、ignoreDependencyInterface

    在依赖注入bean的时候,如果当前Bean实现了某些接口是我们特点的,不用依赖注入的则需要进行忽略。在这里进行添加一部分。添加到AbstractAutowireCapableBeanFactoryignoredDependencyInterfaces中。其实也就是上面ApplicationContextAwareProcessor需要回调的类型。

beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

6)、registerResolvableDependency

   设置自动装配(按照类型)的一些特殊规则,当发现需要注册的当前bean实现了某接口,则直接将该Map的value值注入进去。后续getBean时候详细分析。添加到DefaultListableBeanFactoryresolvableDependencies中。

beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

7)、ApplicationListenerDetector

    又是一个特殊的BeanPostProcessor,同时实现了MergedBeanDefinitionPostProcessor(MergedBeanDefinition的回调,即合并了父类的属性等的beanDefinition)和DestructionAwareBeanPostProcessor(注销实现了的ApplicatonEvent)。

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
        Class<?> beanType, String beanName);

    default void resetBeanDefinition(String beanName) {
    }
}
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;

    default boolean requiresDestruction(Object bean) {
        return true;
    }
}
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, 
    MergedBeanDefinitionPostProcessor {

    private final transient AbstractApplicationContext applicationContext;

    private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);
    
    public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, 
        Class<?> beanType, String beanName) {
        this.singletonNames.put(beanName, beanDefinition.isSingleton());
    }
}

    ApplicationListenerDetector实现了上面所有机接口的方法,并且能看出在BeanDefinition进行Merge后会调用postProcessMergedBeanDefinition方法将值注入到singletonNames中使用,后续分析。

8)、LOAD_TIME_WEAVER_BEAN_NAME

1)、containsBean

    使用BeanFactory的containsBean方法判断是否拥有Bean,很多地方都使用到了,所以这里看一下是怎么进行判断的。最终会调用到AbstractBeanFactory的方法,先获取真实的beanName(传入的可能是别名);从单利bean或者BeanDefinition容器中获取;最后从父工厂中获取。非常清晰的思路。

public boolean containsBean(String name) {
    String beanName = transformedBeanName(name);
    if (containsSingleton(beanName) || containsBeanDefinition(beanName)) {
        return (!BeanFactoryUtils.isFactoryDereference(name) || isFactoryBean(name));
    }
    // Not found -> check parent.
    BeanFactory parentBeanFactory = getParentBeanFactory();
    return (parentBeanFactory != null && parentBeanFactory.containsBean(originalBeanName(name)));
}

    其实很多地方也调用了transformedBeanName方法,因为我们传入的可能是别名,不是beanName。所以需要查找真正的BeanName,这里也分析一下。

protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

BeanFactoryUtils.transformedBeanName

    当前传入的可能是FactoryBean类型的bean,并且是获取FactoryBean的,所以在BeanFactoryUtils中处理(就是截取字符串):

public static String transformedBeanName(String name) {
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

containsSingleton

    从DefaultSingletonBeanRegistrysingletonObjects中判断

public boolean containsSingleton(String beanName) {
    return this.singletonObjects.containsKey(beanName);
}

containsBeanDefinition

    从DefaultListableBeanFactorybeanDefinitionMap中判断

public boolean containsBeanDefinition(String beanName) {
    return this.beanDefinitionMap.containsKey(beanName);
}

2)、添加织入相关处理

if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    // Set a temporary ClassLoader for type matching.
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(
        beanFactory.getBeanClassLoader()));
}

    如果需要进行织入则添加LoadTimeWeaverAwareProcessor,ContextTypeMatchClassLoader。

9)、Environment相关注成Bean

    上一篇分析过StandardEnvironment的初始化过程,从System中获取了很多配置让Spring容器进行管理,现在为了方便,直接在ApplicationContext(或者说BeanFactory)中进行注入。所以相关环境变量直接在容器中是可以拿到的,当然Spring Boot的Actuator也是建立在该基础上的,详细见上一篇

if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
    beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, 
        getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME,
        getEnvironment().getSystemEnvironment());
}

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值