一步一步解读 refresh源码

refresh()

refresh()方法代码如下:

@Override
public void refresh() throws BeansException, IllegalStateException {
    
    
    synchronized (this.startupShutdownMonitor) {
    
    
        // 准备此上下文以进行刷新
        prepareRefresh();
        // 告诉子类刷新内部 bean 工厂
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 准备在此上下文中使用的 bean 工厂
        prepareBeanFactory(beanFactory);
        try {
    
    
            // 允许在上下文子类中对 bean 工厂进行后处理
            postProcessBeanFactory(beanFactory);
            // 调用在上下文中注册为 bean 的工厂处理器
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注册 拦截 bean创建的 bean 处理器
            registerBeanPostProcessors(beanFactory);
            // 初始化此上下文的消息源
            initMessageSource();
            // 为此上下文初始化事件多播器
            initApplicationEventMulticaster();
            // 初始化特定上下文子类中的其他特殊bean
            onRefresh();
            // 检查监听器 bean 并注册它们
            registerListeners();
            // 实例化所有剩余的(非惰性初始化)单例。
            finishBeanFactoryInitialization(beanFactory);
            // 最后一步:发布相应的事件
            finishRefresh();
        }
        catch (BeansException ex) {
    
    
            if (logger.isWarnEnabled()) {
    
    
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }
            // 销毁已经创建的单例以避免悬空资源
            destroyBeans();
            // 重置“活动”标志。
            cancelRefresh(ex);
            // 将异常传播给调用者
            throw ex;
        }
        finally {
    
    
            // 重置 Spring 核心中的公共自省缓存,因为我们可能不再需要单例 bean 的元数据...re...
            resetCommonCaches();
        }
    }
}

首先是对上下文进行刷新:

 // 准备此上下文以进行刷新
prepareRefresh();

1. prepareRefresh

创建和准备了 Environment 对象:

  • Environment 的作用之一是为后续 @Value,值注入时提供键值

流程如下图所示:

image-20220802135345191

prepareRefresh重点是准备了初始环境,我们跟进prepareRefresh源码实现:

image-20220802134525624

可以看到获取环境配置的代码,继续跟进

image-20220802134555225

扫描二维码关注公众号,回复: 14540189 查看本文章

里面创建了一个标准的环境:

image-20220802134621875

我们在prepareRefresh();这打个断点也能看到里面的environment:

image-20220802130258156

我们将第一步走完,可以看到environment被初始化成了StandardEnvironment

image-20220802130723299

我们执行一个表达式测试一下:

image-20220802131017494

比如说我们测试一下有没有JAVA_HOME的键值信息,我们发现是可以执行查询到的,所以说此时,一些系统的环境都已经加载到Spring中了:

image-20220802131108848

我们将 展开可以看到JAVA环境变量和系统环境变量:

image-20220802131249623

两个环境变量的内容如下:

image-20220802131415137

我们也可以通过下面代码获取这两个环境变量

// 获取系统环境变量
System.getenv().keySet().stream().forEach(s -> System.out.println(s));
// java环境变量
System.getProperties().keySet().stream().forEach(s -> System.out.println(s));

同样,我们也可以使用StandardEnvironment获取这两个环境变量

StandardEnvironment env = new StandardEnvironment();
env.getSystemEnvironment().keySet().stream().forEach(s -> System.out.println(s));
env.getSystemProperties().keySet().stream().forEach(s -> System.out.println(s));

当然也可以加一个环境变量:

// 加一个环境变量
env.getPropertySources().addLast(new ResourcePropertySource("my",new ClassPathResource("1.properties")));

2. obtainFreshBeanFactory

获取(或创建)BeanFactory 来刷新 内部 bean 工厂:

  • BeanFactory 的作用是负责 bean 的创建、依赖注入和初始化
  • BeanDefinition 作为 bean 的设计蓝图,规定了 bean 的特征,如单例多例、依赖关系、初始销毁方法等
  • BeanDefinition 的来源有多种多样,可以是通过 xml 获得、通过配置类获得、通过组件扫描获得,也可以是编程添加

ApplicationContext没有Bean初始化,依赖注入等功能他都没有,他得简介的调用BeanFactory 来对Bean进行管理,ApplicationContext委托给BeanFactory 来干这些活,ApplicationContext做的是扩展的活,Bean的核心功能是在BeanFactory 中。

执行流程如下:

image-20220802135450655

我们继续跟进源码:

/** 
* 告诉子类刷新内部 bean 工厂。
* @return 新的 BeanFactory 实例
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    
    
	refreshBeanFactory();
	return getBeanFactory();
}

里面调用了接口中的两个方法:

/**
 * 子类必须实现此方法才能执行实际的配置加载。
 * 该方法在任何其他初始化工作之前由 {@link #refresh()} 调用。
 * <p>子类要么创建一个新的bean工厂并持有对它的引用,
 * 或返回它拥有的单个 BeanFactory 实例。在后一种情况下,它将
 * 如果多次刷新上下文,通常会抛出 IllegalStateException。
 * @throws BeansException 如果 bean 工厂的初始化失败
 * @throws IllegalStateException 如果已经初始化并且多次刷新
 * 不支持尝试
 */
protected abstract void refreshBeanFactory() throw BeansExceptionIllegalStateException
/**
 * 子类必须在此处返回其内部 bean 工厂。他们应该实施
 * 高效查找,因此可以重复调用而不会降低性能。
 * <p>注意:子类之前应该检查上下文是否仍然处于活动状态
 * 返回内部 bean 工厂。内部工厂一般应该是
 * 一旦上下文关闭,则认为不可用。
 * @return 此应用程序上下文的内部 bean 工厂(从不 {@code null})
 * @throws IllegalStateException 如果上下文还没有包含内部 bean 工厂
 * (通常如果 {@link #refresh()} 从未被调用过)或者如果上下文已经
 * 已经关闭
 * @see #refreshBeanFactory()
 * @see #closeBeanFactory()
 */
@Override
公共抽象 ConfigurableListableBeanFactory getBeanFactory() throw IllegalStateException

我们在这加个断点看看具体干了什么:

image-20220802140334875

断点出我们执行下一步,看一下refreshBeanFactory的实现:

首先是一个Boolean,这个refreshed变量是用来判断有没有调用过refresh

image-20220802140555622

给BeanFactory实现一个序列化id,这个就对于解读没啥大用了:

image-20220802140859005

下面就是getBeanFactory方法:

这里直接返回了beanFactory

image-20220802141011560

这是个啥?他之前创建过吗?怎么直接返回了?

这个其实在我们创建上下文时候就已经创建了,我们可以在GenericApplicationContext.java中找到答案:

在调用构造的时候就已经初始化beanFactory了

image-20220802141200433

注意这里的ClassPathXmlApplicationContext上下文是调用的另一个refreshBeanFactory的实现

@Override
protected final void refreshBeanFactory() throws BeansException {
	if (hasBeanFactory()) {
		destroyBeans();
		closeBeanFactory();
	}
	try {
		DefaultListableBeanFactory beanFactory = createBeanFactory();
		beanFactory.setSerializationId(getId());
		customizeBeanFactory(beanFactory);
		loadBeanDefinitions(beanFactory);
		synchronized (this.beanFactoryMonitor) {
			this.beanFactory = beanFactory;
		}
	}
	catch (IOException ex) {
		throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
	}
}

会用新的beanFactory覆盖旧的beanFactory

这里面实现获取BeanFactory 的方法是loadBeanDefinitions(beanFactory) ,下面来测试一下:

我们在xml中配置一个bean:

image-20220802143133541

执行后可以看到加载了我们xml文件中的Bean,bean的所有信息都在value里

image-20220802143223713

BeanDefinition测试(读取Bean方式)

1.xml方式读取

public class BeanDefinitionTest {
    
    
    public static void main(String[] args) {
    
    
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 1.xml方式读取
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions("classpath:app.xml");
        System.out.println(reader.getBeanFactory());
    }
}

得到从app.xml获取的bean

image-20220802144751105

把这个常用的加到监控变量中:

image-20220802145609849

2.组件扫描

加一个Bean3 添加 @Component

image-20220802145307282

编写下面代码:

// 2.组件扫描
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
scanner.scan("com.yyl.refresh");

执行可以看到Bean3加到了BeanFactory中:

(其他的是一些bean处理器的)

image-20220802145709723

4.编程方式(Bean构建器)

// 4.编程方式添加
beanFactory.registerBeanDefinition("Bean4", BeanDefinitionBuilder.genericBeanDefinition(Bean4.class).getBeanDefinition());

image-20220802150449750

编程方式比较可控,比如我们设置为多例:

// 4.编程方式添加
beanFactory.registerBeanDefinition("Bean4", BeanDefinitionBuilder
        .genericBeanDefinition(Bean4.class)
        .setScope("prototype")
        .getBeanDefinition());
// 再打印一下
System.out.println(beanFactory.getBean("Bean4"));
System.out.println(beanFactory.getBean("Bean4"));
System.out.println(beanFactory.getBean("Bean4"));

结果如下,生成的是三个不同的对象:

image-20220802150810837

再比如我们加一个初始化函数:

public class Bean4 {
    
    
    public void initMethod(){
    
    
        System.out.println("Bean init!!!");
    }
}

// 4.编程方式添加
beanFactory.registerBeanDefinition("Bean4", BeanDefinitionBuilder
        .genericBeanDefinition(Bean4.class)
        .setScope("prototype")
        .setInitMethodName("initMethod")
        .getBeanDefinition());
System.out.println(beanFactory.getBean("Bean4"));
System.out.println(beanFactory.getBean("Bean4"));
System.out.println(beanFactory.getBean("Bean4"));

结果如下:

image-20220802150913868

3. prepareBeanFactory

准备在此上下文中使用的 bean 工厂,完善BeanFactory,把一些重要的成员变量初始化:

  • StandardBeanExpressionResolver 来解析 SpEL
  • ResourceEditorRegistrar 会注册类型转换器,并应用 ApplicationContext 提供的 Environment 完成 ${ } 解析
  • 特殊 bean 指 beanFactory 以及 ApplicationContext,通过 registerResolvableDependency 来注册它们
  • ApplicationContextAwareProcessor 用来解析 Aware 接口
  • ApplicationListenerDetector 用来识别容器中 ApplicationListener 类型的 bean

执行流程如下:

(右侧绿色表示初始化的)

image-20220802151958061

下面我们追踪一下源码:

都是完善BeanFactory参数:

image-20220802153417146

首先是要找到El解析器里的addPropertyEditorRegistrar:注册一组类型转化器

右键我们执行个语句测试一下这个注册器是干嘛滴:

image-20220802152904152

执行找到我们Bean4的语句

beanFactory.getBeanExpressionResolver().evaluate("#{@Bean4}",new BeanExpressionContext(beanFactory,null))

发现是能查到我们刚注册的结果的:

image-20220802152833593

可以,能解析EL表达式了

下面我们深入探究下里面的ResourceEditorRegistrar资源类型转化器,我们可以看到不同的资源类型用不同转化器转化

image-20220802160905695

添加Bean后处理器:扩展功能

// Configure the bean factory with context callbacks.
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 interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

4. postProcessBeanFactory

这一步是空实现,留给子类扩展,做补充

  • 一般 Web 环境的 ApplicationContext 都要利用它注册新的 Scope,完善 Web 下的 BeanFactory
  • 体现的是模板方法设计模式

直接看源码:

首先我们可以看到确实是空实现:

/**
 * 按照标准修改应用上下文的内部bean工厂
 * 初始化。所有 bean 定义都将被加载,但没有 bean
 * 将被实例化。这允许注册特殊的
 * 某些 ApplicationContext 实现中的 BeanPostProcessors 等。
 * @param beanFactory 应用上下文使用的bean工厂
 */
protected postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    
    
}

来吧看看子类对他补充了啥吧,这里我们主要看一个web里对这个方法的实现:

没有的先要加一个依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

5. invokeBeanFactoryPostProcessors(beanFactory);

调用在上下文中注册的 BeanFactory 的后处理器:进一步完善BeanFactory

  • beanFactory 后处理器,充当 beanFactory 的扩展点,可以用来补充或修改 BeanDefinition
  • ConfigurationClassPostProcessor – 解析 @Configuration、@Bean、@Import、@PropertySource 等
  • PropertySourcesPlaceHolderConfigurer – 替换 BeanDefinition 中的 ${ }
  • MapperScannerConfigurer – 补充 Mapper 接口对应的 BeanDefinition

执行流程如下:

image-20220802165039166

我们看一下源码:

image-20220802165329040

首先他调用了配置后处理器的方法,具体实现太多,里面主要配置两个后处理器BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
		beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);	
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
      beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

下面我们来进行一个后处理器小测试

ConfigurationClassPostProcessor后处理器

新建一个测试类编写如下方法:

package com.yyl.refresh;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

public class AppPostProcess {
    
    
    public static void main(String[] args) {
    
    

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("muConfig",MyConfig.class);
        // context.registerBean("configurationClassPostProcessor", ConfigurationClassPostProcessor.class);
        context.refresh();
        System.out.println();
    }

    @Configuration
    static class MyConfig{
    
    
        public MyConfig(){
    
    }

        @Bean
        public Bean1 bean1(){
    
    
            return new Bean1();
        }
        @Bean
        public Bean2 bean2(){
    
    
            return new Bean2();
        }
    }

    static class Bean1{
    
    

    }
    static class Bean2{
    
    

    }
}

默认没有用到Bean1和Bean2,是不会主动加到BeanFactory中的

我们在第4步与第5步加一个断点,debug下:

image-20220802171500845

我们看到只有一个我们注册的Bean:

image-20220802171611320

当我们加上一个后处理器:ConfigurationClassPostProcessor

context.registerBean("configurationClassPostProcessor", ConfigurationClassPostProcessor.class);

再运行,当执行到第四步时,只有两个我们注册的Bean:

image-20220802171804085

当执行完第五步,我们发现执行了后处理器的方法,把配置中的Bean也加到Bean工厂里来了

image-20220802171950023

下面我们在使用@import测试下

@Configuration
@Import(Bean3.class)
static class MyConfig{
    
    
    public MyConfig(){
    
    }
    @Bean
    public Bean1 bean1(){
    
    
        return new Bean1();
    }
    @Bean
    public Bean2 bean2(){
    
    
        return new Bean2();
    }
}

static class Bean3{
    
    

}

重新Debug,可以看到Bean3也能通过后处理器加载进来

image-20220802190412384

再加一个资源文件的注解

@Configuration
@Import(Bean3.class)
@PropertySource("classpath:1.properties")
static class MyConfig{
    
    
    public MyConfig(){
    
    }
    @Bean
    public Bean1 bean1(){
    
    
        return new Bean1();
    }
    @Bean
    public Bean2 bean2(){
    
    
        return new Bean2();
    }
}

运行,可以看到资源文件也能加载到环境当中

image-20220802190713455

MapperScannerConfigurer后处理器

// mybatis后处理器
context.registerBean("mapperScannerConfigurer", MapperScannerConfigurer.class,bd -> {
    // 找包名
    bd.getPropertyValues().add("basePackage","com.yyl.mapper");
});

设置查找包下接口注入BeanFactory

image-20220802191901158

// mybatis后处理器
context.registerBean("mapperScannerConfigurer", MapperScannerConfigurer.class,bd -> {
    // 找包名
    bd.getPropertyValues().add("basePackage","com.yyl.mapper");
    // 找配置了@mapper注解的
    bd.getPropertyValues().add("annotationClass","org.apache.ibatis.annotations.Mapper");
});

这回就只有roleMapper了

image-20220802192119013

PropertySourcesPlaceholderConfigurer后处理器

解析${}的值

context.registerBean("propertySourcesPlaceholderConfigurer", PropertySourcesPlaceholderConfigurer.class);

测试一下,新增一个Bean4:

static class Bean4 {
    
    
    private String value;
    public String getValue() {
    
    
        return value;
    }
    public void setValue(String value) {
    
    
        this.value = value;
    }
}

将${JAVA_HOME}设置到value上

context.registerBean("bean4",Bean4.class,bd -> {
    
    
    bd.getPropertyValues().add("value","${JAVA_HOME}");
});

如果没加这个处理器是不能显示的

image-20220802192922599

加上PropertySourcesPlaceholderConfigurer后处理器

context.registerBean("propertySourcesPlaceholderConfigurer", PropertySourcesPlaceholderConfigurer.class);

再运行没有问题:

image-20220802193010635

6. registerBeanPostProcessors(beanFactory);

注册 bean创建的 bean 后处理器(在Bean的声明周期对Bean进行扩展)

  • bean 后处理器,充当 bean 的扩展点,可以工作在 bean 的实例化、依赖注入、初始化阶段
  • AutowiredAnnotationBeanPostProcessor 功能有:解析 @Autowired,@Value 注解
  • CommonAnnotationBeanPostProcessor 功能有:解析 @Resource,@PostConstruct,@PreDestroy
  • AnnotationAwareAspectJAutoProxyCreator 功能有:为符合切点的目标 bean 自动创建代理

三个处理器执行时机如下图所示:

image-20220802232703089

执行流程如下:

beanDefinition中有没有Bean实现了PostProcess接口,有就说明不是一般的Bean是一个Bean后处理器,Spring把这中Bean实例化出来方法放到 beanPostProcess中

image-20220802193539566

下面探究一下源码:

按照四组规定先后执行的Bean的顺序,

  • 首先,注册实现 PriorityOrdered 的 BeanPostProcessor。
  • 接下来,注册实现 Ordered 的 BeanPostProcessor。
  • 现在,注册所有常规的 BeanPostProcessor。
  • 最后,重新注册所有内部 BeanPostProcessor。

源码太多不贴了。

来看一个测试案例:

package com.yyl.refresh;

import org.springframework.context.support.GenericApplicationContext;

public class BeanPostProcess {
    
    
    public static void main(String[] args) {
    
    
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("bean1",Bean1.class);
        context.registerBean("bean2",Bean2.class);
        context.registerBean("bean3",Bean3.class);
        context.refresh();
        System.out.println(context.getBean(Bean1.class).bean2);
        System.out.println(context.getBean(Bean1.class).bean3);
    }

    static class Bean1 {
    
    
        private Bean2 bean2;
        private Bean3 bean3;
    }
    static class Bean2 {
    
    

    }
    static class Bean3 {
    
    

    }

}

这样打印是打印不出值的,因为他们之间还没有一个依赖注入关系

image-20220802194205821

传统的依赖注入是这样的:

context.registerBean("bean1",Bean1.class,bd -> {
    
    
    bd.getPropertyValues().add("bean2",new RuntimeBeanReference("bean2"));
    bd.getPropertyValues().add("bean3",new RuntimeBeanReference("bean3"));
});

image-20220802194638105

但是比较麻烦,我们可以用自动装配:

// 使用自动装配
context.registerBeanDefinition("bean1", BeanDefinitionBuilder
        .genericBeanDefinition(Bean1.class)
        .setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME)
        .getBeanDefinition());

image-20220802195011802

还是麻烦,第三代出来了,@Autowired

@Autowired
private Bean2 bean2;
@Autowired
private Bean3 bean3;

诶!结果发现都没注入:

image-20220802195150497

为啥呢? 这是因为咱们少了一个Bean的后处理器

加上后处理器

// Bean后处理器 @Autowire
context.registerBean("autowiredAnnotationBeanPostProcessor", AutowiredAnnotationBeanPostProcessor.class);

image-20220802195333793

AutowiredAnnotationBeanPostProcessor处理器

支持什么注解?

这个答案我们从他源码的构造函数里可以找到,支持Spring标准注解 @Autowire和@Value

image-20220802211015109

出这两个外,他还支持@Inject注解,这是官方的一个注解

作用1:探测候选构造

给Bean1加两个构造器

static class Bean1 {
    
    
    private Bean2 bean2;
    private Bean3 bean3;
    public Bean1(Bean3 bean3) {
    
    
        this.bean3 = bean3;
    }
    public Bean1(Bean2 bean2) {
    
    
        this.bean2 = bean2;
    }
    public void setBean2(Bean2 bean2) {
    
    
        this.bean2 = bean2;
    }
    public void setBean3(Bean3 bean3) {
    
    
        this.bean3 = bean3;
    }
}

使用AutowiredAnnotationBeanPostProcessor找出候选构造器

AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
// 找候选构造器
Constructor<?>[] constructors = beanPostProcessor.determineCandidateConstructors(Bean1.class, "bean1");
System.out.println(Arrays.toString(constructors));

但是我们在构造器上没有加@Autowired他是找不到的

image-20220802212659680

给Bean1的一个构造加上注解:

@Autowired
public Bean1(Bean2 bean2) {
    
    
    this.bean2 = bean2;
}

image-20220802212750233

我们把其中一个构造删了,也是可以查到的,因为他找不到别的构造器了,候选构造只有一个

static class Bean1 {
    
    
    private Bean2 bean2;
    private Bean3 bean3;
    public Bean1(Bean3 bean3) {
    
    
        this.bean3 = bean3;
    }
    
    public void setBean2(Bean2 bean2) {
    
    
        this.bean2 = bean2;
    }
    public void setBean3(Bean3 bean3) {
    
    
        this.bean3 = bean3;
    }
}

image-20220802212846651

但是我们再两个构造器上都加上@Autowired呢?

他会报错构造器已存在

image-20220802213504532

作用2:进行装配(值,引用)

package com.yyl.refresh;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.support.GenericApplicationContext;

import javax.annotation.Resource;
import java.lang.reflect.Constructor;
import java.util.Arrays;

public class BeanPostProcess {
    
    
    public static void main(String[] args) {
    
    
        GenericApplicationContext context = new GenericApplicationContext();
        
        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("bean3", Bean3.class);

        context.refresh();
        AutowiredAnnotationBeanPostProcessor beanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
        beanPostProcessor.setBeanFactory(context.getDefaultListableBeanFactory());
        Bean1 bean1 = new Bean1();
        System.out.println("注入之前:"+bean1);
        // 处理Bean的属性
        beanPostProcessor.postProcessProperties(context.getBeanDefinition("bean1").getPropertyValues(),bean1,"bean1");
        System.out.println("注入之后:"+bean1);

    }

    static class Bean1 {
    
    
        @Autowired
        private Bean2 bean2;
        @Autowired
        private Bean3 bean3;
//        @Value("${JAVA_HOME}")
        private Resource resource;

        @Override
        public String toString() {
    
    
            return "Bean1{" +
                    "bean2=" + bean2 +
                    ", bean3=" + bean3 +
                    ", resource=" + resource +
                    '}';
        }
    }

    static class Bean2 {
    
    

    }

    static class Bean3 {
    
    

    }

}

image-20220802215351738

CommonAnnotationBeanPostProcessor处理器

识别@Resource、 @PostConstruct、@PreDestroy

package com.yyl.refresh;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.support.GenericApplicationContext;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

public class BeanPostProcessCommon {
    public static void main(String[] args) {
        GenericApplicationContext context = new GenericApplicationContext();

        context.registerBean("bean1", Bean1.class);
        context.registerBean("bean2", Bean2.class);
        context.registerBean("commonAnnotationBeanPostProcessor", CommonAnnotationBeanPostProcessor.class);
        context.refresh();
        System.out.println(context.getBean(Bean1.class).bean2);
        // 关闭容器  打印destory1
        context.close();
    }


    static class Bean1 {
        private Bean2 bean2;

        @Resource
        public void setBean2(Bean2 bean2) {
            System.out.println("setBean2(Bean2 bean2)");
            this.bean2 = bean2;
        }

        @PostConstruct
        public void init1(){
            System.out.println("init1");
        }

        @PreDestroy
        public void destory1(){
            System.out.println("destory1");
        }
    }

    static class Bean2 {

    }
}

image-20220802221844146

7. initMessageSource();

初始化此上下文的消息源,实现国际化
容器中一个名为 messageSource 的 bean,如果没有,则提供空的 MessageSource 实现

执行流程如下图所示:

image-20220802232857157

8. initApplicationEventMulticaster();

为此上下文初始化事件多播器,用来发事件的

  • 用来发布事件给监听器
  • 可以从容器中找名为 applicationEventMulticaster 的 bean 作为事件广播器,若没有,也会新建默认的事件广播器
  • 可以调用 ApplicationContext.publishEvent(事件对象) 来发布事件

执行流程如下:

image-20220802233002340

我们使用如下方式进行发事件:

context.publishEvent(new Object());
context.publishEvent(new ApplicationEvent("source") {
    
    
    @Override
    public Object getSource() {
    
    
        return super.getSource();
    }
});

9. onRefresh();

初始化特定上下文子类中的其他特殊bean

这一步是空实现,留给子类扩展

  • SpringBoot 中的子类可以在这里准备 WebServer,即内嵌 web 容器
  • 体现的是模板方法设计模式

image-20220802233600523

10. registerListeners();

检查监听器 bean 并注册它们

  • 用来接收事件

  • 一部分监听器是事先编程添加的、另一部分监听器来自容器中的 bean、还有一部分来自于 @EventListener 的解析

  • 实现 ApplicationListener 接口,重写其中 onApplicationEvent(E e) 方法即可

  • initApplicationEventMulticaster发的事件由事件监听器来接收

执行流如下所示:

image-20220802233931691

registerListeners三种监听器

三种添加方式:

img

运行结果:

img

Bean3没有打印出来:缺少必要的后处理器

image-20220802234344977

加一个事件,三个监听器都收到了

image-20220802234428681

image-20220802234454522

在第三步,会加一个监听器

image-20220802234818822

在第八步会初始化监听器

image-20220802234850801

11. finishBeanFactoryInitialization(beanFactory);

实例化所有剩余的(非惰性初始化)单例。

12. finishRefresh();

最后一步:发布相应的事件

猜你喜欢

转载自blog.csdn.net/weixin_45525272/article/details/126132243
今日推荐