深入理解Spring源码(4)- bean工厂的准备工作

91 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 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());

	}
}

运行结果