Spring启动流程解析-3-准备BeanFactory

一,Spring启动流程概览

Spring的IoC容器在实现控制反转和依赖注入的过程中,可以划分为两个阶段:

  • 容器启动阶段

  • Bean实例化阶段

容器初始化

  1. 加载配置

  2. 分析配置信息

  3. 将Bean信息装配到BeanDefinition

  4. 将Bean信息注册到相应的BeanDefinitionRegistry

  5. 其他后续处理

容器实例化

  1. 根据策略实例化对象

  2. 装配依赖

  3. Bean初始化前处理

  4. 对象初始化

  5. 对象其他处理

  6. 注册回调接口

二,Spring启动流程详解

准备BeanFactory

这个阶段主要是当Spring获取了BeanFactory之后,还要做些处理工作(配置工厂的上下文),如:上下文的ClassLoader和BeanPostProcessor。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 内部BeanFactory使用Context上下文的类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 配置BeanFactory的Context上下文回调
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    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接口不在普通工厂中注册为可解析类型
    // MessageSource 注册(找到并自动装配)为一个Bean
    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.
    // 注册早期的后处理器用来将内部Bean检测为ApplicationListeners。
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // 如果发现LoadTimeWeaver,则准备织入
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        // 给类型匹配设置一个临时的ClassLoader
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 注册默认的environment
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    // 注册systemProperties
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    // 注册systemEnvironment
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
}

BeanExpressionResolver

通过将值作为表达式进行评估来解析值。它的唯一实现类是StandardBeanExpressionResolver

PropertyEditor

Spring使用PropertyEditor的来实现对象和字符串之间的转换。有时用与对象本身不同的方式表示属性可能更为方便。如:“2019-09-13”字符串形式阅读起来更友好,但也可以将任何方便阅读的日期表现形式转换为日期对象。

Spring提供了很多内置的PropertyEditor,它们都位于org.springframework.beans.propertyeditors包中。默认情况下,大多数由BeanWrapperImpl注册。

描述

ByteArrayPropertyEditor

字节数组属性编辑器。字符串将地转换为相应的字节形式。默认情况下由BeanWrapperImpl注册。

ClassEditor

将表示类的字符串解析为实际类,反之亦然。当找不到类时,将抛出IllegalArgumentException。默认情况下由BeanWrapperImpl注册。

CustomBooleanEditor

布尔属性编辑器。默认情况下由BeanWrapperImpl注册,但是可以通过将其自定义实例注册为自定义编辑器来覆盖。

CustomCollectionEditor

集合属性编辑器,可将任何源集合转换为给定的目标集合类型。

CustomDateEditor

Date自定义属性编辑器,支持自定义DateFormat。

CustomNumberEditor

Number自定义属性编辑器。可用于任何Number子类,如Integer,Long,Float,Double。默认情况下由BeanWrapperImpl注册,但是可以通过将其自定义实例注册为自定义编辑器来覆盖。

FileEditor

将字符串解析为java.io.File对象。默认情况下由BeanWrapperImpl注册。

InputStreamEditor

单向属性编辑器,根据文本字符串生成(通过中间的ResourceEditor和Resource)InputStream,因此InputStream属性可以直接设置为Strings。默认情况下由BeanWrapperImpl注册。请注意,默认用法不会关闭InputStream!

LocaleEditor

将字符串解析为Locale对象,反之亦然(String格式为[country] [variant],与Locale的toString()方法提供的功能相同)。默认情况下由BeanWrapperImpl注册。

PatternEditor

将字符串解析为java.util.regex.Pattern对象,反之亦然。

PropertiesEditor

将字符串转换为Properties对象。默认情况下由BeanWrapperImpl注册。

StringTrimmerEditor

修剪字符串的属性编辑器。 允许将空字符串转换为Null值。

URLEditor

将URL的字符串表示形式解析为实际的URL对象。默认情况下由BeanWrapperImpl注册。

ResourceEditor

资源描述符属性编辑器,可将字符串转换为Resource属性。如:将file:C:/myfile.txt或classpath:myfile.txt转换为Resource属性。 该路径可能包含$ {...}占位符,将被解析为Environment属性,如$ {user.dir}。默认情况下,无法解析的占位符将被忽略。

Aware感知

如果在某个Bean里面想要使用Spring框架提供的功能,可以通过Aware接口来实现。通过实现 Aware 接口,Spring 可以在启动时,调用接口定义的方法,并将 Spring 底层的一些组件注入到自定义的 Bean 中。

描述

ApplicationContextAware

当ApplicationContext创建实现ApplicationContextAware接口的Bean实例时,将为该Bean实例提供对该ApplicationContext的引用。

ApplicationEventPublisherAware

为Bean实例提供对ApplicationEventPublisherAware的引用。

BeanFactoryAware

为Bean实例提供对BeanFactory的引用

BeanNameAware

获取Bean在BeanFactory中配置的名字

MessageSourceAware

为Bean实例提供对MessageSource的引用

EnvironmentAware

获得Environment支持,这样可以获取环境变量

ResourceLoaderAware

获得资源加载器以获得外部资源文件

代码示例

public class AwareBean implements ApplicationContextAware, BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("=====>" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx)
            throws BeansException {
        System.out.println("=====>" + ctx.getBean("awareBean"));
    }
}

Xml配置文件

<?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="awareBean" class="xxx.xxx.aware.AwareBean"/>
</beans>

忽略自动装配

Spring在ConfigurableListableBeanFactory接口中提供了2个可以忽略自动装配的方法:

// 自动装配时忽略指定接口或类的依赖注入
void ignoreDependencyType(Class<?> type);

// 忽略接口实现类中存在依赖外部的Bean注入
void ignoreDependencyInterface(Class<?> ifc);

忽略自动装配的做法使得一些基础组件(如:ApplicationContext或BeanFactory)依赖在自动装配时被忽略,而由框架统一设置依赖。如ApplicationContextAware接口的设置会在ApplicationContextAwareProcessor类中完成。

示例公用xml文件

<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 class="xxx.xxx.TestBean" name="testB1;testB2"/>

    <bean id="human" class="xxx.xxx.autowired.Human"/>
    <bean id="humanService" class="xxx.xxx.autowired.HumanService" autowire="byName"/>
    <!-- 去掉下面的注释,则ignoreDependencyType生效 -->
    <!--<bean class="xxx.xxx.autowired.HumanAutowiringProcessor"/>-->

    <bean id="list" class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <value>foo</value>
                <value>bar</value>
            </list>
        </constructor-arg>
    </bean>
    <bean id="ignoreImpl" class="xxx.xxx.autowired.IgnoreImpl" autowire="byName" />
    <!-- 去掉下面的注释,则ignoreDependencyInterface生效 -->
    <!--<bean class="xxx.xxx.autowired.InterfaceIgnoreProcessor"/>-->
</beans>

ignoreDependencyType

public class Human {
    private String name;

    public Human( String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

实现了BeanFactoryPostProcessor的忽略自动装配处理器,这里是忽略的类。

public class HumanAutowiringProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        
        beanFactory.ignoreDependencyType(Human.class);
    }
}

ignoreDependencyInterface

接口类

public interface IgnoreInterface {
    void setList(List<String> list);
}

实现类

public class IgnoreImpl implements IgnoreInterface {

    private List<String> list;

    @Override
    public void setList(List<String> list) {
        this.list = list;
        System.out.println("ok.......");
    }

    public List<String> getList() {
        return list;
    }
}

实现了BeanFactoryPostProcessor的忽略自动装配处理器,这里忽略的是接口。

public class InterfaceIgnoreProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
            throws BeansException {
        beanFactory.ignoreDependencyInterface(IgnoreInterface.class);
    }
}

BeanPostProcessor

如果想在Spring容器中完成Bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理,就需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值