关键词:prepareBeanFactory(beanFactory)方法postProcessBeanFactory(beanFactory)方法
今天的知识点和流程要比创建BeanFactory要少很多,理解起来会稍微轻松简单一些。
一.prepareBeanFactory(beanFactory)
见名知意:beanFactory的准备工作,对各种属性进行填充
1.设置BeanFactory的类加载器为ApplicationContex的类加载器
2.设置beanFacory的语言表达式处理器
2.1:怎么来理解语言表达式呢?例如spel,spring的el表达式。
那处理器呢?就是对语言表达式进行解析处理
// 设置beanFactory的表达式语言处理器,参数为表达式语言处理器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
2.2:我们来看看这个新创建的语言表达式吧。我们进入的是 new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())。
public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
//在表达式语言处理器内==>创建了表达式语言解析器(该类的doParse方法是进行解析操作的)==>创建了一个SpringEL表达式的配置类(里面只是进行了一些属性的赋值)
this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
}
2.3:然后我们进入一下SpringEl表达式的配置类
其实就是调用重载方法进行属性初始化赋值
public SpelParserConfiguration(@Nullable SpelCompilerMode compilerMode, @Nullable ClassLoader compilerClassLoader) {
this(compilerMode, compilerClassLoader, false, false, Integer.MAX_VALUE);
}
3.为BeanFactory增加一个默认的属性编辑器。对于属性编辑器的内容解释我写在代码段的注释中
// 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具类
//addPropertyEditorRegistrar(名词翻译:增加一个属性编辑注册)
/**
* 名词翻译:增加一个属性编辑注册器:addPropertyEditorRegistrar
* 作用:
* Date类型的一些操作:将String类型的时间转为Date类型
* 自定义类型的处理:
* 比如:Address类中有省市县三个属性值,一般来说我们需要依次赋值
* 但是我们可以通过属性编辑器转:将xx省_xx市_xx区,转化为Address
* 然后赋值给Address
*
* 自定义扩展:1.创建一个customer{name,Address} Address{province,city,town}
* 2.创建一个实现PropertyEditorSupport接口的编辑器
* 3.让Spring能过识别到此编辑器,自定义实现一个属性编辑器注册器,
* 实现了PropertyEditorRegistrar接口
* 4.让Spring可以识别到注册器
* 5.CustomEditorConfigurer类下的propertyEditorRegistrars属性数组内,包含了注册器
*
* 样例在:selfEditor包下
*/
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
3.1关于注释中自定义扩展的第四点。怎么让Spring可以识别到注册器中,给中XML配置文件的示例
<!--方式一:CustomEditorConfigurer该类是将属性编辑器注册器 添加到Spring容器内-->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<!--propertyEditorRegistrars是一个数组所以要使用<list>标签-->
<list>
<!--将我们的注册器加入到数组中-->
<bean class="com.mashibing.selfEditor.lewis.AddressPropertyEditorRegistrar"></bean>
</list>
</property>
</bean>
<!--方式二:CustomEditorConfigurer该类是将属性编辑器注册器 添加到Spring容器内-->
<!--
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.mashibing.selfEditor.lewis.Address">
<value>com.mashibing.selfEditor.lewis.AddressPropertyEditor</value>
</entry>
</map>
</property>
</bean>
-->
4.添加Bean的后置增强器
4.1还记得xxxAware类型的接口吗?对于实现该类型接口的Bean对象,初始化Bean对象的过程中Spring会为其设置上对应的xxx容器属性。
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
4.2我们进入一下ApplicationContextAwareProcessor这个类中,来看下该类中的两个方法,留个印象,然后思考为什么第5点中会忽视一些自动装配的接口。
/**
* 接口beanPostProcessor规定的方法,会在bean创建时,实例化后,初始化前,对bean对象应用
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//判断要初始化的Bean是否实现类以下接口,如果没实现就不进行对应的操作
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
//Bean实现了以上的接口
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
// 检测bean上是否实现了某个aware接口,有的话进行相关的调用
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
invokeAwareInterfaces(bean);
}
return bean;
}
/**
* 如果某个bean实现了某个aware接口,给指定的bean设置相应的属性值
*
* @param 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);
}
}
5.设置要忽略自动装配的接口
5.1发现了吗?这些要进行忽视的接口在第四点中已经通过ApplicationContextAwareProcessor设置到工厂中,到用到的时候工厂是可以用到的,所以对下列的xxxWare进行了忽视。
// 忽略的原因在于==>在上面的方法中已经对接下来的接口进行处理了
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
6.设置几个自动装配的特殊规则。例如在进行IOC初始化的时候有多个实现,那么就使用指定的对象进行注入
// 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
7.注册一个Bean的后置增强器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
7.1来看一下上面代码段中的ApplicationListenerDetector类,此类用来检测bean是否实现了ApplicationListener接口,两个作用:
1、实例化完成之后,如果bean的单例的并且属于ApplicationListener接口,则加入到多播器中
2、bean销毁之前,如果bean是一个applicationListener,则从多播器中提前删除
8.增加对AspectJ的支持
// aspectj提供了两种织入方式,第一种是通过特殊编译器,在编译器,将aspectj语言编写的切面类织入到java类中,第二种是类加载期织入,就是下面的load time weaving,此处后续讲
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()));
}
9.注册默认的系统环境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());
}
二.postProcessBeanFactory(beanFactory)方法
1.点击进去之后,发现这是一个空实现
作用:子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}