携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情
前文已经介绍了Spring的核心方法以及Spring是如何解析配置文件中的内容,包括对自定义标签的一个扩展工作,接下来就该进行对beanFactory的一个准备工作。
一、对beanFactory的准备
先看源码
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
//设置beanFactory的classloader为当前的classloader
beanFactory.setBeanClassLoader(getClassLoader());
//设置beanfactory的表达式语言处理器
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));
//设置要忽略自动装配的接口。
//在使用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提供了两种织入方式,第一种是通过特殊编译器,在编译器,将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、设置beanFactory的classLoader为当前的classloader
2、设置一个语言表达器
3、设置一个默认的propertyEditor,主要是对bean的属性等设置管理的一个工具
4、添加applicationContextAwareProcessor,用来完成某些Aware对象的注入
5、设置一些忽略接口
6、设置几个自动装配的特殊规则
7、注册BPP
8、注册默认的系统环境bean到一级缓存中
这里面先忽略对aop的一些准备,比较重要的就是设置了一个属性编辑器的注册和添加一个beanPostProcessor
属性编辑器
这个方法中注册了ResourceEditorRegistrar的类,这个类的作用就是提前注册简单通用常用类型的属性编辑器
接着看一下属性编辑器的注册
在Bean实例化的过程中doCreateBean有个createBeanInstance方法
通过调用createBeanInstance会调用到instantiateBean中的initBeanWrapper方法
最后在initBeanWrapper方法中调用registerCustomEditors方法完成各种属性编辑器的调用
那这个属性编辑器是干什么用的呢?
试想一下,配置文件中配置的各种属性值都是字符串类型,那为什么解析到对应实体中的字段上时没有报错呢?其实这就是各种编辑器的作用,对于编辑器的编辑转换过程,会放到会后bean实例化的内容中讲解。下面说一下自定义的扩展实现。
自定义属性编辑器的扩展
准备两个对象一个Address,一个Customer
package com.spring.selfEditor;
public class Address {
private String province;
private String city;
private String town;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getTown() {
return town;
}
public void setTown(String town) {
this.town = town;
}
@Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", city='" + city + '\'' +
", town='" + town + '\'' +
'}';
}
}
package com.spring.selfEditor;
public class Customer {
private String name;
private Address address;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", address=" + address +
'}';
}
}
准备编辑器
package com.spring.selfEditor;
import java.beans.PropertyEditorSupport;
public class AddressPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
String[] s = text.split("_");
Address address = new Address();
address.setProvince(s[0]);
address.setCity(s[1]);
address.setTown(s[2]);
this.setValue(address);
}
}
准备注册编辑器
package com.spring.selfEditor;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
public class AddressPropertyEditorRegister implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Address.class,new AddressPropertyEditor());
}
}
准备配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean id="customer" class="com.spring.selfEditor.Customer">
<property name="name" value="zhangsan"></property>
<property name="address" value="河北省_邯郸市_武安市"></property>
</bean>
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.spring.selfEditor.AddressPropertyEditorRegister"></bean>
</list>
</property>
</bean>
<!-- <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">-->
<!-- <property name="customEditors">-->
<!-- <map>-->
<!-- <entry key="com.spring.selfEditor.Address">-->
<!-- <value>com.spring.selfEditor.AddressPropertyEditor</value>-->
<!-- </entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- </bean>-->
</beans>
准备测试类
package com.spring.selfEditor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class text {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("selfEditor.xml");
Customer bean = context.getBean(Customer.class);
System.out.println(bean.toString());
}
}
运行结果