一、概述
prepareBeanFactory的主要流程如下,我将一一解析下面的代码,一些不太重要的代码我会略过。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
// 设置beanFactory的classloader为当前context的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));
// 设置要忽略自动装配的接口,很多同学理解不了为什么此处要对这些接口进行忽略,原因非常简单,这些接口的实现是由容器通过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());
}
}
二、主要方法
(一)、addPropertyEditorRegistrar
addPropertyEditorRegistrar()方法是向容器中添加属性编辑器的注册器,这里是实现拓展的拓展点。点开来看的好像挺简单的,也没什么东西,但是它的注册器和编辑器比较重要。
@Override
public void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar) {
Assert.notNull(registrar, "PropertyEditorRegistrar must not be null");
this.propertyEditorRegistrars.add(registrar);
}
注册器:
注册器接口就做了一件事,就是把编辑器注册了进去
public interface PropertyEditorRegistrar {
/**
* Register custom {@link java.beans.PropertyEditor PropertyEditors} with
* the given {@code PropertyEditorRegistry}.
* <p>The passed-in registry will usually be a {@link BeanWrapper} or a
* {@link org.springframework.validation.DataBinder DataBinder}.
* <p>It is expected that implementations will create brand new
* {@code PropertyEditors} instances for each invocation of this
* method (since {@code PropertyEditors} are not threadsafe).
* @param registry the {@code PropertyEditorRegistry} to register the
* custom {@code PropertyEditors} with
*/
void registerCustomEditors(PropertyEditorRegistry registry);
}
编辑器:
编辑器又两个比较重要的方法,用setAsText对数据进行转化,用setValue方法将数据传递出去。
public class PropertiesEditor extends PropertyEditorSupport {
/**
* Convert {@link String} into {@link Properties}, considering it as
* properties content.
* @param text the text to be so converted
*/
@Override
public void setAsText(@Nullable String text) throws IllegalArgumentException {
Properties props = new Properties();
if (text != null) {
try {
// Must use the ISO-8859-1 encoding because Properties.load(stream) expects it.
props.load(new ByteArrayInputStream(text.getBytes(StandardCharsets.ISO_8859_1)));
}
catch (IOException ex) {
// Should never happen.
throw new IllegalArgumentException(
"Failed to parse [" + text + "] into Properties", ex);
}
}
setValue(props);
}
/**
* Take {@link Properties} as-is; convert {@link Map} into {@code Properties}.
*/
@Override
public void setValue(Object value) {
if (!(value instanceof Properties) && value instanceof Map) {
Properties props = new Properties();
props.putAll((Map<?, ?>) value);
super.setValue(props);
}
else {
super.setValue(value);
}
}
}
三、拓展点
(一)、编辑器
我们需要自定义注册器和解析器,实现对特定标签,特定字符的解析。实现的目的是对地址字符串进行解析,将其变成省市区。
实体类:
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 + '\'' +
'}';
}
}
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 +
'}';
}
}
注册器:
public class AddressPropertyEditorRegistrar implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(Address.class,new AddressPropertyEditor());
}
}
编辑器:
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);
}
}
配置文件:
<?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="customer" class="com.mashibing.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.mashibing.selfEditor.AddressPropertyEditorRegistrar"></bean>
</list>
</property>
</bean>
</beans>
运行结果显示,得到了我们配置文件需要注入的类。