Spring启动流程(三)——准备BeanFactory

这个阶段主要是当Spring获取了BeanFactory之后,还要做些处理工作(配置工厂的上下文),如:上下文的ClassLoader和BeanPostProcessor。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 内部BeanFactory使用Context上下文的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 配置BeanFactory的Context上下文回调
    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接口不在普通工厂中注册为可解析类型
    // 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.
    // 注册早期的后处理器用来将内部Bean检测为ApplicationListeners。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 如果发现LoadTimeWeaver,则准备织入
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // 给类型匹配设置一个临时的ClassLoader
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册默认的environment
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    // 注册systemProperties
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    // 注册systemEnvironment
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

BeanExpressionResolver

通过将值作为表达式进行评估来解析值。它的唯一实现类是StandardBeanExpressionResolver。

PropertyEditor

Spring使用PropertyEditor的来实现对象和字符串之间的转换。有时用与对象本身不同的方式表示属性可能更为方便。如:“2020-10-30”字符串形式阅读起来更友好,但也可以将任何方便阅读的日期表现形式转换为日期对象。
Spring提供了很多内置的PropertyEditor,它们都位于org.springframework.beans.propertyeditors包中。默认情况下,大多数由BeanWrapperImpl注册。

描述
ByteArrayPropertyEditor字节数组属性编辑器。字符串将转换为相应的字节形式。默认情况下由BeanWrapperImpl注册。
ClassEditor将表示类的字符串解析为实际类,反之亦然。当找不到类时,将抛出IllegalArgumentException。默认情况下由BeanWrapperImpl注册。
CustomBooleanEditor布尔属性编辑器。默认情况下由BeanWrapperImpl注册,但是可以通过将其自定义实例注册为自定义编辑器来覆盖。
CustomCollectionEditor集合属性编辑器,可将任何源集合转换为给定的目标集合类型。
CustomDateEditorDate自定义属性编辑器,支持自定义DateFormat。
CustomNumberEditorNumber自定义属性编辑器。可用于任何Number子类,如Integer,Long,Float,Double。默认情况下由BeanWrapperImpl注册,但是可以通过将其自定义实例注册为自定义编辑器来覆盖。
FileEditor将字符串解析为java.io.File对象。默认情况下由BeanWrapperImpl注册。
InputStreamEditor单向属性编辑器,根据文本字符串生成(通过中间的ResourceEditor和Resource)InputStream,因此InputStream属性可以直接设置为Strings。默认情况下由BeanWrapperImpl注册。请注意,默认用法不会关闭InputStream!
LocaleEditor将字符串解析为Locale对象,反之亦然(String格式为[country] [variant],与Locale的toString()方法提供的功能相同)。默认情况下由BeanWrapperImpl注册。
PatternEditor将字符串解析为java.util.regex.Pattern对象,反之亦然。
PropertiesEditor将字符串转换为Properties对象。默认情况下由BeanWrapperImpl注册。
StringTrimmerEditor修剪字符串的属性编辑器。 允许将空字符串转换为Null值。
URLEditor将URL的字符串表示形式解析为实际的URL对象。默认情况下由BeanWrapperImpl注册。
ResourceEditor资源描述符属性编辑器,可将字符串转换为Resource属性。如:将file:C:/myfile.txt或classpath:myfile.txt转换为Resource属性。 该路径可能包含$ {…}占位符,将被解析为Environment属性,如$ {user.dir}。默认情况下,无法解析的占位符将被忽略。

Aware感知

如果在某个Bean里面想要使用Spring框架提供的功能,可以通过Aware接口来实现。通过实现 Aware 接口,Spring 可以在启动时,调用接口定义的方法,并将 Spring 底层的一些组件注入到自定义的 Bean 中。

描述
ApplicationContextAware当ApplicationContext创建实现ApplicationContextAware接口的Bean实例时,将为该Bean实例提供对该ApplicationContext的引用。
ApplicationEventPublisherAware为Bean实例提供对ApplicationEventPublisherAware的引用。
BeanFactoryAware为Bean实例提供对BeanFactory的引用
BeanNameAware获取Bean在BeanFactory中配置的名字
MessageSourceAware为Bean实例提供对MessageSource的引用
EnvironmentAware获得Environment支持,这样可以获取环境变量
ResourceLoaderAware获得资源加载器以获得外部资源文件

代码示例

public class AwareBean implements ApplicationContextAware, BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("=====>" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx)
            throws BeansException {
        System.out.println("=====>" + ctx.getBean("awareBean"));
    }
}

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="awareBean" class="cn.lzh.aware.AwareBean"/>
</beans>

忽略自动装配

Spring在ConfigurableListableBeanFactory接口中提供了2个可以忽略自动装配的方法:

// 自动装配时忽略指定接口或类的依赖注入
void ignoreDependencyType(Class<?> type);

// 忽略接口实现类中存在依赖外部的Bean注入
void ignoreDependencyInterface(Class<?> ifc);

忽略自动装配的做法使得一些基础组件(如:ApplicationContext或BeanFactory)依赖在自动装配时被忽略,而由框架统一设置依赖。如ApplicationContextAware接口的设置会在ApplicationContextAwareProcessor类中完成。

BeanPostProcessor

如果想在Spring容器中完成Bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理,就需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值