Spring源码学习第五天==>prepareBeanFactory(beanFactory)

关键词:prepareBeanFactory(beanFactory)方法postProcessBeanFactory(beanFactory)方法

今天的知识点和流程要比创建BeanFactory要少很多,理解起来会稍微轻松简单一些。


一.prepareBeanFactory(beanFactory) 

      见名知意:beanFactory的准备工作,对各种属性进行填充

     1.设置BeanFactory的类加载器为ApplicationContex的类加载器

     2.设置beanFacory的语言表达式处理器

        2.1:怎么来理解语言表达式呢?例如spel,spring的el表达式。

                那处理器呢?就是对语言表达式进行解析处理

// 设置beanFactory的表达式语言处理器,参数为表达式语言处理器
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));

       2.2:我们来看看这个新创建的语言表达式吧。我们进入的是 new  StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())。

public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
		//在表达式语言处理器内==>创建了表达式语言解析器(该类的doParse方法是进行解析操作的)==>创建了一个SpringEL表达式的配置类(里面只是进行了一些属性的赋值)
		this.expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
	}

        2.3:然后我们进入一下SpringEl表达式的配置类

               其实就是调用重载方法进行属性初始化赋值

public SpelParserConfiguration(@Nullable SpelCompilerMode compilerMode, @Nullable ClassLoader compilerClassLoader) {
		this(compilerMode, compilerClassLoader, false, false, Integer.MAX_VALUE);
	}

     3.为BeanFactory增加一个默认的属性编辑器。对于属性编辑器的内容解释我写在代码段的注释中

// 为beanFactory增加一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具类
		//addPropertyEditorRegistrar(名词翻译:增加一个属性编辑注册)
		/**
		 * 名词翻译:增加一个属性编辑注册器:addPropertyEditorRegistrar
		 * 作用:
		 * 		Date类型的一些操作:将String类型的时间转为Date类型
		 * 		自定义类型的处理:
		 * 					比如:Address类中有省市县三个属性值,一般来说我们需要依次赋值
		 * 						但是我们可以通过属性编辑器转:将xx省_xx市_xx区,转化为Address
		 * 						然后赋值给Address
		 * 						
		 * 	自定义扩展:1.创建一个customer{name,Address}  Address{province,city,town}
		 * 	         2.创建一个实现PropertyEditorSupport接口的编辑器
		 * 	         3.让Spring能过识别到此编辑器,自定义实现一个属性编辑器注册器,
		 * 	           实现了PropertyEditorRegistrar接口
		 * 	         4.让Spring可以识别到注册器
		 * 	         5.CustomEditorConfigurer类下的propertyEditorRegistrars属性数组内,包含了注册器
		 *
		 * 	样例在:selfEditor包下
		 */
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        3.1关于注释中自定义扩展的第四点。怎么让Spring可以识别到注册器中,给中XML配置文件的示例

 <!--方式一:CustomEditorConfigurer该类是将属性编辑器注册器  添加到Spring容器内-->
    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="propertyEditorRegistrars">
            <!--propertyEditorRegistrars是一个数组所以要使用<list>标签-->
            <list>
                <!--将我们的注册器加入到数组中-->
                <bean class="com.mashibing.selfEditor.lewis.AddressPropertyEditorRegistrar"></bean>
            </list>
        </property>
    </bean>
    <!--方式二:CustomEditorConfigurer该类是将属性编辑器注册器  添加到Spring容器内-->
<!--
    <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
        <property name="customEditors">
            <map>
                <entry key="com.mashibing.selfEditor.lewis.Address">
                    <value>com.mashibing.selfEditor.lewis.AddressPropertyEditor</value>
                </entry>
            </map>
        </property>
    </bean>
-->

     4.添加Bean的后置增强器

        4.1还记得xxxAware类型的接口吗?对于实现该类型接口的Bean对象,初始化Bean对象的过程中Spring会为其设置上对应的xxx容器属性。

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));

        4.2我们进入一下ApplicationContextAwareProcessor这个类中,来看下该类中的两个方法,留个印象,然后思考为什么第5点中会忽视一些自动装配的接口。

	/**
	 * 接口beanPostProcessor规定的方法,会在bean创建时,实例化后,初始化前,对bean对象应用
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return
	 * @throws BeansException
	 */
	@Override
	@Nullable	
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		//判断要初始化的Bean是否实现类以下接口,如果没实现就不进行对应的操作
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
			return bean;
		}
		//Bean实现了以上的接口
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				// 检测bean上是否实现了某个aware接口,有的话进行相关的调用
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}



	/**
	 * 如果某个bean实现了某个aware接口,给指定的bean设置相应的属性值
	 *
	 * @param bean
	 */
	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof EnvironmentAware) {
			((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
		}
		if (bean instanceof EmbeddedValueResolverAware) {
			((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
		}
		if (bean instanceof ResourceLoaderAware) {
			((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
		}
		if (bean instanceof ApplicationEventPublisherAware) {
			((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
		}
		if (bean instanceof MessageSourceAware) {
			((MessageSourceAware) bean).setMessageSource(this.applicationContext);
		}
		if (bean instanceof ApplicationContextAware) {
			((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
		}
	}

     5.设置要忽略自动装配的接口

        5.1发现了吗?这些要进行忽视的接口在第四点中已经通过ApplicationContextAwareProcessor设置到工厂中,到用到的时候工厂是可以用到的,所以对下列的xxxWare进行了忽视。

	// 忽略的原因在于==>在上面的方法中已经对接下来的接口进行处理了
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

     6.设置几个自动装配的特殊规则。例如在进行IOC初始化的时候有多个实现,那么就使用指定的对象进行注入

// 设置几个自动装配的特殊规则,当在进行ioc初始化的如果有多个实现,那么就使用指定的对象进行注入
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

     7.注册一个Bean的后置增强器

beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

        7.1来看一下上面代码段中的ApplicationListenerDetector类,此类用来检测bean是否实现了ApplicationListener接口,两个作用:

             1、实例化完成之后,如果bean的单例的并且属于ApplicationListener接口,则加入到多播器中

             2、bean销毁之前,如果bean是一个applicationListener,则从多播器中提前删除

     8.增加对AspectJ的支持

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

     9.注册默认的系统环境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());
		}

二.postProcessBeanFactory(beanFactory)方法

    1.点击进去之后,发现这是一个空实现

      作用:子类覆盖方法做额外的处理,此处我们自己一般不做任何扩展工作,但是可以查看web中的代码,是有具体实现的

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值