本次主要跟进AbstractApplicationContext中refres()方法中的:
// beanFactory的准备工作,对各种属性进行填充
prepareBeanFactory(beanFactory);
----
/ Tell the internal bean factory to use the context's class loader etc.
// 设置beanFactory的classloader为当前context的classloader
beanFactory.setBeanClassLoader(getClassLoader());
// 设置beanfactory的表达式语言处理器 注:spel解析器-->spel解析器配置对象
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
// 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具类
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 添加beanPostProcessor,ApplicationContextAwareProcessor此类用来完成某些Aware对象的注入
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 设置要忽略自动装配的接口,很多同学理解不了为什么此处要对这些接口进行忽略,原因非常简单,这些接口的实现是由容器通过set方法进行注入的,
// 所以在使用autowire进行注入的时候需要将这些接口进行忽略
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
// 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入
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.
// 注册BPP
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
// 增加对AspectJ的支持,在java中织入分为三种方式,分为编译器织入,类加载器织入,运行期织入,编译器织入是指在java编译器,采用特殊的编译器,将切面织入到java类中,
// 而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面,运行期织入则是采用cglib和jdk进行切面的织入
// 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()));
}
// Register default environment beans.
// 注册默认的系统环境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());
}
其中这里面比较重要的是自定义属性编辑器的实现:
其中:需要实现自定义属性编辑器的话,必须实现如下的规则:
1.自定义实现了ProperEditorSupport接口的编辑器
2.让spring能够识别到此编辑器,自定义实现一个属性编辑器的注册器, 实现了PropertyEditorRegistor接口
3.让spring能够识别到对应的注册器
beanFactoryProstProcessor:执行后置处理器
比如日期定义的内容是2021-12-04 ,然后要求自动解析为年为2021, 月为12 日为04
- 先看bean类Date:
```java
public class Date {
private String id;
private Time time;
//省略 get 、set 、tostring方法
}
Time类
//时间类
public class Time {
private String year;
private String month;
private String day;
//省略 get 、set 、tostring方法
}
2. 让spring能够识别到此编辑器,新建TimesPropertyEditorRegistor 实现PropertyEditorRegistrar接口
```java
public class TimesPropertyEditorRegistor implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Time.class,new TimePropertyEditor());
}
}
3.让spring能够识别到对应的注册器, 新建TimePropertyEditor 继承PropertyEditorSupport
public class TimePropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
String[] strings=text.split("-");
Time time=new Time();
time.setYear(strings[0]);
time.setMonth(strings[1]);
time.setDay(strings[2]);
this.setValue(time);
}
}
最后我们看下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="time" class="com.mashibing.selfEditorHxp.Date">
<property name="id" value="1" ></property>
<property name="time" value="2021-12-04"></property>
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.mashibing.selfEditorHxp.TimesPropertyEditorRegistor"></bean>
</list>
</property>
</bean>
<!-- <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">-->
<!-- <property name="customEditors">-->
<!-- <map>-->
<!-- <entry key="com.mashibing.selfEditorHxp.Time"-->
<!-- value="com.mashibing.selfEditorHxp.TimesPropertyEditorRegistor">-->
<!-- </entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- </bean>-->
</beans>
然后是main方法进行测试:
public class Test {
public static void main(String[] args) {
MyClassPathXmlApplicationContext ac = new MyClassPathXmlApplicationContext("selfEditorHxp.xml");
Date bean = ac.getBean(Date.class);
System.out.println(bean);
}
执行之后 然后我们查看效果:
每天学习一点坚持把源码的内容都是摸熟