Sping源码(六)— prepareBeanFactory()

前言

前几篇已经介绍lBeanFactory的创建已经xml配置文件中自定义标签和默认标签的解析过程,此时的BeanFactory中已经包含了xml文件中的标签属性。但BeanFactory中还有一些本身重要的属性没有填充,所以接着方法继续往下看BeanFactory中的属性是如何填充的。

refresh
refresh()主流程中前几个方法已经介绍过,这里不过多赘述,去掉后面的无用代码,我们这篇帖子主要看prepareBeanFactory方法中做了些什么。

public void refresh() throws BeansException, IllegalStateException {
    
    
		synchronized (this.startupShutdownMonitor) {
    
    
			// Prepare this context for refreshing.
			/**
			 * 前戏,做容器刷新前的准备工作
			 * 1、设置容器的启动时间
			 * 2、设置活跃状态为true
			 * 3、设置关闭状态为false
			 * 4、获取Environment对象,并加载当前系统的属性值到Environment对象中
			 * 5、准备监听器和事件的集合对象,默认为空的集合
			 */
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 创建容器对象:DefaultListableBeanFactory
			// 加载xml配置文件的属性值到当前工厂中,最重要的就是BeanDefinition
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// beanFactory的准备工作,对各种属性进行填充
			prepareBeanFactory(beanFactory);
		}
	}

prepareBeanFactory
见名知意,这个方法中也是为了BeanFactory做准备工作,所以刚上来设置了BeanFacroty的类加载器。

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());
		}
	}

StandardBeanExpressionResolver

这个方法主要是创建了一个标准的Bean表达式的解析器。主要是用来对spel表达式的解析。
其中类之间的关系是Resolver处理类 包含了-> spelParser的解析类 包含了 -> spelConfiguration配置类。其中具体的解析过程是在SpelExpressionParser中的doParseExpression()方法完成。


	/**
	 * 默认表达式前缀
	 *
	 * Default expression prefix: "#{". */
	public static final String DEFAULT_EXPRESSION_PREFIX = "#{";

	/**
	 * 默认表达式后缀
	 *
	 * Default expression suffix: "}". */
	public static final String DEFAULT_EXPRESSION_SUFFIX = "}";


	private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;

	private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;

public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
    
    
		this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
	}

 public SpelParserConfiguration(@Nullable SpelCompilerMode compilerMode, @Nullable ClassLoader compilerClassLoader,
			boolean autoGrowNullReferences, boolean autoGrowCollections, int maximumAutoGrowSize) {
    
    

		this.compilerMode = (compilerMode != null ? compilerMode : defaultCompilerMode);
		this.compilerClassLoader = compilerClassLoader;
		this.autoGrowNullReferences = autoGrowNullReferences;
		this.autoGrowCollections = autoGrowCollections;
		this.maximumAutoGrowSize = maximumAutoGrowSize;
	}

SpelExpressionParser
省略具体解析过程。知道使用时会调用doParseExpression方法即可。

public SpelExpressionParser(SpelParserConfiguration configuration) {
    
    
		Assert.notNull(configuration, "SpelParserConfiguration must not be null");
		this.configuration = configuration;
	}

@Override
	protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
    
    
		return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);
	}

回到prepareBeanFactory主方法,看下面的具体方法。

addPropertyEditorRegistrar

这个方法主要是对类属性的一个扩展,比如说Customer类中引用了Address变量。Address中包含了省市区的属性,但Customer中对address的值是省_市_区,将值捏合成了一个,这时可通过自定义的扩展对类中属性进行拆分。

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()));
	}

先看方法的具体执行流程。

ResourceEditorRegistrar
addPropertyEditorRegistrar()方法会为BeanFacroty中PropertyEditorRegistrar属性赋值,在PropertyEditorRegistrar的构造器中,会对类中属性进行初始化赋值,并在类中包含了一个registerCustomEditors()方法。
registerCustomEditors方法会将Spring中默认的一些类注册到Editors中,默认的会执行overrideDefaultEditor操作。
registerCustomEditors方法会在Spring后面的源码中进行调用,这里不过多讲解

public class ResourceEditorRegistrar implements PropertyEditorRegistrar {
    
    

	public ResourceEditorRegistrar(ResourceLoader resourceLoader, PropertyResolver propertyResolver) {
    
    
			this.resourceLoader = resourceLoader;
			this.propertyResolver = propertyResolver;
		}
		
		@Override
		public void registerCustomEditors(PropertyEditorRegistry registry) {
    
    
			ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
			doRegisterEditor(registry, Resource.class, baseEditor);
			//省略部分doRegisterEditor代码...
	
			if (this.resourceLoader instanceof ResourcePatternResolver) {
    
    
				doRegisterEditor(registry, Resource[].class,
						new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader, this.propertyResolver));
			}
		}
	
	private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
    
    
			if (registry instanceof PropertyEditorRegistrySupport) {
    
    
				((PropertyEditorRegistrySupport) registry).overrideDefaultEditor(requiredType, editor);
			}
			else {
    
    
				registry.registerCustomEditor(requiredType, editor);
			}
		}
}

ResourceEditor
ResourceEditor类继承了PropertyEditorSupport,PropertyEditorSupport实现了PropertyEditor类,其中ResourceEditor类包含了一些对类属性的一些实现。包括setAsText,setValue等一些方法。

public class ResourceEditor extends PropertyEditorSupport {
    
    
	public void setAsText(String text) throws java.lang.IllegalArgumentException {
    
    
	        if (value instanceof String) {
    
    
	            setValue(text);
	            return;
	        }
	        throw new java.lang.IllegalArgumentException(text);
	    }
	 public void setValue(Object value) {
    
    
	        this.value = value;
	        firePropertyChange();
	    }
}

结合ResourceEditor和ResourceEditorRegistrar两者来看的话,对属性的扩展就是将具体的class类,通过Editor定义好具体的逻辑后,通过Spring框架的识别,而后根据自己定义的逻辑来针对具体的class类的属性进行处理。

自定义类属性扩展

根据上面介绍的执行流程,仿照Spring框架的写法:

  1. 需要类实现PropertyEditorRegistrar类并实现自己的registerCustomEditors方法将类注册到Editors类中
  2. 在自定义的Editors类中,重写setAsText方法,实现类中的属性自定义扩展。
  3. 让自定义的Registrar类能够被Spring发现,并调用。

自定义类
Customer类中包含着Address属性,此时Customer对address的属性设置是“”省_市_区“”的格式,到Address类中要拆分成对应的值。

public class Customer {
    
    

    private String name;
    private Address address;
}

public class Address {
    
    
    private String province;
    private String city;
    private String town;
}

实现Registrar
实现Registrar,调实现registerCustomEditors注册。

public class AddressPropertyEditorRegistrar implements PropertyEditorRegistrar {
    
    

    @Override
    public void registerCustomEditors(PropertyEditorRegistry registry) {
    
    
        registry.registerCustomEditor(Address.class,new AddressPropertyEditor());
    }
}
//根据参数text属性实现自定义扩展
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配置
这里的xml采用了两种方法配置,目的是让Spring框架可以发现我们自定义的Editor,并进行调用。将我们自定义的Editor填充到CustomEditorConfigurer类中的customEditors属性其实就可让Spring框架发现并调用。这里埋个小坑,会在后面源码具体执行调用customEditors属性时再填。

 <bean id="customer" class="com.xxx.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.xxx.selfEditor.AddressPropertyEditorRegistrar"></bean>-->
<!--            </list>-->
<!--        </property>-->
<!--    </bean>-->
    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="com.xxx.selfEditor.Address">
                    <value>com.xxx.selfEditor.AddressPropertyEditor</value>
                </entry>
            </map>
        </property>
    </bean>

ignoreDependencyInterface

忽略自动装配的接口,这些接口的实现是由容器通过set方法进行注入的,所以在使用autowire进行注入的时候需要将这些接口进行忽略。
源码中忽略类的方法有两个,代表着不同的含义,具体可以看这篇帖子,关于ignoreDependencyInterface的方法讲述的很细。

/**
	 * 自动装配时忽略的类
	 *
	 * Ignore the given dependency type for autowiring:
	 * for example, String. Default is none.
	 * @param type the dependency type to ignore
	 */
	void ignoreDependencyType(Class<?> type);

	/**
	 * 自动装配时忽略的接口
	 *
	 * Ignore the given dependency interface for autowiring.
	 * <p>This will typically be used by application contexts to register
	 * dependencies that are resolved in other ways, like BeanFactory through
	 * BeanFactoryAware or ApplicationContext through ApplicationContextAware.
	 * <p>By default, only the BeanFactoryAware interface is ignored.
	 * For further types to ignore, invoke this method for each type.
	 * @param ifc the dependency interface to ignore
	 * @see org.springframework.beans.factory.BeanFactoryAware
	 * see org.springframework.context.ApplicationContextAware
	 */
	void ignoreDependencyInterface(Class<?> ifc);

猜你喜欢

转载自blog.csdn.net/weixin_43936962/article/details/132309291