【Spring 源码】ApplicationContext 容器的加载原理(二)
文章目录
容器的功能扩展
主要方法:prepareBeanFactory(beanFactory);
在 prepareBeanFactory()
之前,对容器的初始化已经完成,此方法中,可以看到许多对 Spring 功能的扩展,比如 Spring 表达式语言或者 AspectJ 的支持。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 将 BeanFactory 的 ClassLoader 设置为 Context 的 ClassLoader
beanFactory.setBeanClassLoader(getClassLoader());
// 添加 Spring 表达式语言的支持
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 添加属性管理器
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 对实现 Aware 接口的类进行前置设置
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.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// 对事件监听器做前置处理
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// 添加对 AspectJ 的支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// 添加系统环境 Bean
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());
}
}
一、添加 Spring 表达式语言的支持
主要方法:beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
Spring 表达式语言缩写为 SpEL,能够支持运行时查询、操作对象图、对象方法调用,是一个强大的表达式语言,同时能够配置 bean 定义。
SpEL 使用 #{…} 作为定界符,可以在定界符中使用整数、String类型的值或者引用其他的 bean,更加强大的是可以在定界符中使用运算符号进行表达式的计算。
1. 使用例子
下面是一个简单的例子,只是展示简单的用法,这边并不讨论更多场景下的用法,而是要理解源码的结构。
- 目录结构:
|-- src
|-- com.test
|-- Main.java
|-- MyBean.java
|-- MyBean.xml
- MyBean.java:
public class MyBean {
private String message;
private Double price;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "MyBean{" +
"message='" + message + '\'' +
", price=" + price +
'}';
}
}
- MyBean.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myBean" class="com.test.MyBean">
<property name="message" value="#{'Hello World!'}" />
<property name="price" value="#{10.1 + 20}" />
</bean>
</beans>
- Main.java:
public class Main {
public static void main(String[] args) {
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("MyBean.xml"));
MyBean bean = (MyBean) beanFactory.getBean("myBean");
System.out.println(bean.toString());
}
}
2. StandardBeanExpressionResolver 的初始化
StandardBeanExpressionResolver 的主要功能在于 BeanExpressionResolver 接口的 evaluate()
方法,实际的使用在 AbstractBeanFactory 中的 evaluateBeanDefinitionString()
方法,通过这个方法可以根据作用域来解析表达式。
@Nullable
protected Object evaluateBeanDefinitionString(
@Nullable String value,
@Nullable BeanDefinition beanDefinition
) {
if (this.beanExpressionResolver == null) {
return value;
}
// 获取 Bean 的作用域
Scope scope = null;
if (beanDefinition != null) {
String scopeName = beanDefinition.getScope();
if (scopeName != null) {
scope = getRegisteredScope(scopeName);
}
}
// 根据作用域来解析表达式
return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}
二、对实现 Aware 接口的类进行前置处理
主要方法:beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
查看 ApplicationContextAwareProcessor 的继承结构,可以发现实现了 BeanPostProcessor 接口,此接口是用来用作 Bean 的前后置处理,其中重要的两个方法是 postProcessBeforeInitialization()
和 postProcessAfterInitialization()
。
而 ApplicationContextAwareProcessor 则实现了 postProcessBeforeInitialization()
进行前置处理,通过 invokeAwareInterfaces()
方法进行类型判断,来对各种 Bean 进行前置设置。
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(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
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);
}
}
三、忽略某些自动注入的接口
在第三部中有一些类进行了前置处理以后,不再是普通的类,所以 Spring 在进行自动注入的时候,需要排除这些类。
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class)
四、对某些自动注入的类进行值的设置
registerResolvableDependency()
主要用来对某些特定的需要自动注入的类型进行值的设置,主要用于某些没有在容器中定义的类,也就是不需要定义 Bean 而可以直接设置值。
主要方法:
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
@Override
public void registerResolvableDependency(Class<?> dependencyType, @Nullable Object autowiredValue) {
Assert.notNull(dependencyType, "Dependency type must not be null");
if (autowiredValue != null) {
if (!(autowiredValue instanceof ObjectFactory || dependencyType.isInstance(autowiredValue))) {
throw new IllegalArgumentException("Value [" + autowiredValue +
"] does not implement specified dependency type [" + dependencyType.getName() + "]");
}
this.resolvableDependencies.put(dependencyType, autowiredValue);
}
}
五、对事件监听器进行前后置处理
主要方法:beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
ApplicationListenerDetector 类主要是对实现 ApplicationListener 接口的类进行前后置处理,而 ApplicationListener 主要用于对事件监听。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
// 通过获取是否需要监听的值来判断是否需要将监听器注入上下文
Boolean flag = this.singletonNames.get(beanName);
if (Boolean.TRUE.equals(flag)) {
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else if (Boolean.FALSE.equals(flag)) {
if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {
logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " + "but is not reachable for event multicasting by its containing ApplicationContext " + "because it does not have singleton scope. Only top-level listener beans are allowed " + "to be of non-singleton scope.");
}
this.singletonNames.remove(beanName);
}
}
return bean;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) {
if (bean instanceof ApplicationListener) {
try {
ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();
multicaster.removeApplicationListener((ApplicationListener<?>) bean);
multicaster.removeApplicationListenerBean(beanName);
}
catch (IllegalStateException ex) {
}
}
}