读spring源码记录(六)-- prepareBeanFactory

“讲真,我要你现在快乐,毕竟等三十岁再买十八岁时喜欢的裙子就已经没什么意义了。”

承接上篇文章,继续记录

3.prepareBeanFactory(准备上下文使用的bean factory)

首先看一下prepareBeanFactory方法的代码

/**
     * Configure the factory's standard context characteristics,
     * such as the context's ClassLoader and post-processors.
     * @param beanFactory the BeanFactory to configure
     */
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        // 告诉内部bean工厂使用上下文的类加载器等
        //设置类加载器:存在则直接设置/不存在则新建一个默认类加载器
        beanFactory.setBeanClassLoader(getClassLoader());

        //设置EL表达式解析器(Bean初始化完成后填充属性时会用到)
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

        //设置属性注册解析器PropertyEditor
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        // 使用上下文回调配置Bean工厂。
        // 将当前的ApplicationContext对象交给ApplicationContextAwareProcessor类来处理,从而在Aware接口实现类中的注入applicationContext
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        //在工厂的ignoredDependencyInterfaces属性中添加Aware系列接口,
        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接口未在普通工厂中注册为resolvable类型。
        // MessageSource注册为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.
        // 为了监测作为ApplicationListeners的内部类注册早期的post-processor(感觉翻译的怪怪的)
        // 注册ApplicationListenerDetector后置处理器,把实现了ApplicationListener接口的单例对象注册到容器的事件集合中去
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        // 如果发现LoadTimeWeaver,请准备织入(应该是跟AOP相关的属性)
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            // 为匹配类型设置一个临时的ClassLoader
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        // 注册默认的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());
        }
    }

首先第一眼看过去,感觉很简单,就是设置一些属性嘛,我第一遍看的时候,亦是这么感觉,看的很快,感觉没什么东西,但是仔细再看一次,发现了点东西。
前几行都没什么可关注的,都是设置一些属性,到beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));开始,beanFactory开始添加自己的BeanPostProcessor,可以看看addBeanPostProcessor方法的代码,

@Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        // Remove from old position, if any
        this.beanPostProcessors.remove(beanPostProcessor);
        // Track whether it is instantiation/destruction aware
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }
        if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
            this.hasDestructionAwareBeanPostProcessors = true;
        }
        // Add to end of list
        this.beanPostProcessors.add(beanPostProcessor);
    }

/** BeanPostProcessors to apply in createBean */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

/** Indicates whether any InstantiationAwareBeanPostProcessors have been registered */
private volatile boolean hasInstantiationAwareBeanPostProcessors;

/** Indicates whether any DestructionAwareBeanPostProcessors have been registered */
private volatile boolean hasDestructionAwareBeanPostProcessors;

这个代码我们可以看到,这边就是将beanPostProcessor加入对应的List中,这个方法在下面多次调用到。可以注意一点的是CopyOnWriteArrayList这个类是线程安全的,可以在当前类查看,spring用的很多对象都是线程安全的,比我们在学校课本中学到的更丰富一点,值得积累,CopyOnWriteArrayList这个类添加数据时先copy出一个容器(可以简称副本),再往新的容器里添加这个新的数据,最后把新的容器的引用地址赋值给了之前那个旧的的容器地址,但是在添加这个数据的期间,其他线程如果要去读取数据,仍然是读取到旧的容器里的数据。
回到prepareBeanFactory方法中,接下来是切面相关的配置,Load Time Weaving是AspectJ在类加载时期进行代码织入,如果容器中存在名为"loadTimeWeaver"的bean,则添加一个作用域为loadTimeWeaver的后置处理器(上下文将使用一个临时的ClassLoader进行类型匹配,以允许LoadTimeWeaver处理所有实际的bean类。)

// Register default environment beans.
        // 注册默认的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());
        }

最后几行代码,其实很简单,存在名为enviroment, systemProperties, systemEnviroment的几个LocalBean对象,则将其注册到beanFactory的Map<String, Object> singletonObjects这个ConcurrentHashMap上。
prepareBeanFactory就结束了,接下来是回到AbstractApplicationContext查看postProcessBeanFactory(beanFactory)方法。

推荐阅读更多精彩内容

  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 853评论 0 8
  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 2,586评论 4 10
  • 参考W3C Spring教程 Spring致力于J2EE应用的各种解决方案,而不仅仅专注于某一层解决方案。可以说S...
    王侦阅读 346评论 0 5
  • 1. 详解Spring 中如何控制2个bean中的初始化顺序   开发过程中有这样一个场景,2个 bean 初始化...
    未名枯草阅读 554评论 0 0
  • Spring容器高层视图 Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相...
    Theriseof阅读 1,576评论 0 24