【Spring 源码】ApplicationContext 容器的加载原理(二)

本文深入探讨了Spring框架中ApplicationContext容器的加载原理,重点介绍了如何扩展容器功能,包括添加Spring表达式语言支持、处理实现Aware接口的类、自动注入的接口和值的设置,以及事件监听器的处理。文章详细阐述了各个关键步骤,如StandardBeanExpressionResolver的初始化,以及ApplicationContextAwareProcessor和ApplicationListenerDetector的角色。

【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) {  

      }  
   }  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞎叨叨的一天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值