这个阶段主要是当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 | 集合属性编辑器,可将任何源集合转换为给定的目标集合类型。 |
CustomDateEditor | Date自定义属性编辑器,支持自定义DateFormat。 |
CustomNumberEditor | Number自定义属性编辑器。可用于任何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容器中。