Spring源码解析之refresh(3)

【prepareBeanFactory】与【postProcessBeanFactory】

Posted by guyang on April 1, 2022

Spring源码解析之refresh(3)——【prepareBeanFactory】与【postProcessBeanFactory】

上一篇文章介绍了 refresh 方法中的前两个方法,本篇文章我们继续介绍refresh方法中的第三个方法prepareBeanFactory和第四个方法postProcessBeanFactory

一、 prepareBeanFactory

这个方法设置beanFactory的标准上下文特征,为beanFactory设置类加载器、后置处理器等。其中主要注意一下这里面增加了2个beanFactory的后置处理器,由于BeanbeanFactory在Spring中都有后置处理器,所以要优先注意一下。这里需要强调一点:beanFactory在想要拥有后置处理器时,必须通过显示的调用addBeanPostProcessor 才能获得。

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
56
57
58
59
60
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 设置beanFactory的类加载器classLoader为当前context的类加载器.
    beanFactory.setBeanClassLoader(getClassLoader());
    // 设置SpEL表达式解析器(在Bean初始化完成之后填充属性的时候用到)
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    // 添加属性编辑注册器(注册属性编辑器),属性编辑器实际上是属性的类型转换器
    // 因为bean的属性配置都是字符串类型的,实例化的时候要将这些属性转换为实际类型
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 添加beanFactory的后置处理器
    // 在Bean初始化之前,调用ApplicationContextAwareProcessor的postProcessBeforeInitialization
    // 处理所有的Aware接口,进行如下操作:
    // 1. 如果bean实现了EnvironmentAware接口,调用bean.setEnvironment方法
    // 2. 如果bean实现了EmbeddedValueResolverAware接口,调用bean.setEmbeddedValueResolver方法
    // 3. 如果bean实现了ResourceLoaderAware接口,调用bean.setResourceLoader方法
    // 4. 如果bean实现了ApplicationEventPublisherAware接口,调用bean.setApplicationEventPublisher方法
    // 5. 如果bean实现了MessageSourceAware接口,调用bean.setMessageSource方法
    // 6. 如果bean实现了ApplicationContextAware接口,调用bean.setApplicationContext方法
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    // 忽略自动装配,在注入的时候忽略此方法指定的接口类,也就是指定的接口不会被注入进去
    // 可以忽略的原因是: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);

    // BeanFactory interface not registered as resolvable type in a plain factory.
    // MessageSource registered (and found for autowiring) as a bean.
    // 下面这4个class会被加入到beanFactory的resolvableDependencies字段里面缓存着,
    // 为后面处理依赖注入的时候使用DefaultlistableBeanFactory#resolveDependency方法处理依赖关系
    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的后置处理器 事件监听器
    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.1 增加SpEL语言支持

SpEL表达式语言全称为“Spring Expression Language”. SpEL是单独模块, 只依赖于core模块,不依赖其他模块,可以单独使用。

SpEL 使用 #{},作为定界符,所有在大括号中的字符串都将被认为是SpEL.

1
2
3
<bean id="rdsDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="${spring.datasource.druid.url}"/>
 </bean>

prepareBeanFactory中方法中主要通过beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.geBeanclass)); 注册语言解析器,就可以对SpEL进行解析了。

解析的动作是在bean进行初始化的时候会有属性填充的一步,而在这一步中Spring会调用AbstractAutowireCapableBeanFactory类的applyPropertyValue函数来完成功能。

1.2 添加 ApplicationContextAwareProcessor处理器

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)) 方法

我们先看一下类 ApplicationContextAwareProcessor的结构。

1648793538011

该类是BeanPostProcessor的实现类。我们知道BeanPostProcessor类,在bean的init方法执行前后会调用postProcessBeforeInitializationpostProcessAfterinitialization方法。

因此Spring增加了这个类,就是为了在bean的init方法执行时调用postProcessBeforeInitialization方法。那么我们就来具体看看这个方法的实现情况。

1.2.1 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
class ApplicationContextAwareProcessor implements BeanPostProcessor {
	@Override
	@Nullable
	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 方法
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
    }
}

我们从上面的invokeAwareInterfaces方法中可以看出,实现了对应类型的Bean,在初始化之前会根据bean实现的类来获取对应的资源。

执行完上面语句后,beanFactory中便有了ApplicationContextAwareProcessor后置处理器。我们从下面的图片可以看出,此时beanFactory中仅有一个后置处理器。

1648795928209

1.3 设置忽略依赖

当Spring将ApplicationContextAwareProcessor注册之后,在invokeAwareInterfaces方法中调用的Aware类已经不是普通的bean了。如类已经实现了接口ApplicationContextAware时,该类就有applicationContext属性。因此当然需要在Spring做bean的依赖注入的时候忽略它们。而ignoreDependencyInterface功能便是如此。

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

1.4 注册依赖

当注册依赖之后,比如当注册了对BeanFactory的解析依赖之后,当bean的属性注入的时候,一旦检测到属性为BeanFactory类型便会将BeanFactory的实例注入进去。

1648800225299

1.5 事件监听后置处理器ApplicationListenerDetector

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

1648800779896

二、postProcessBeanFactory方法

该方法是一个留给子类的空方法。子类通过重写这个方法来在BeanFactory创建并预准备完成以后做进一步的设置。

三、总结

以上是refresh方法中调用的第三个方法prepareBeanFactory和第四个方法postProcessBeanFactory