Spring注解驱动-扩展原理(七)

1.BeanFactoryPostProcessor

BeanPostProcessor:Bean后置处理器,在bean创建对象初始化前后进行拦截工作。

BeanFactoryPostProcessor:BeanFactory的后置处理器,在BeanFactory标准初始化后调用,可以修改BeanFactory的内容,此时所有Bean定义都已经加载到BeanFactory了,但是Bean还没有创建实例。

创建ExtConfig配置类,MyBeanFactoryPostProcessor类进行测试。

package com.atguigu.ext;

import com.atguigu.bean.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({"com.atguigu.ext"})
public class ExtConfig {
    @Bean
    public Car cat() {
        return new Car();
    }
}
package com.atguigu.ext;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor.postProcessBeanFactory");
        int count = configurableListableBeanFactory.getBeanDefinitionCount();
        System.out.println("当前BeanFactory中有" + count + "个Bean");
        String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
        System.out.println(Arrays.asList(beanDefinitionNames));
    }
}

查看IOC容器的refresh()方法,其中有一个invokeBeanFactoryPostProcessors()方法,用来执行BeanFactoryPostProcessor的方法,在这个方法的后面,可以看到finishBeanFactoryInitialization()方法,在这里才为单实例bean创建对象。

2.BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子类,这是一个接口,它有一个postProcessBeanDefinitionRegistry()方法。它在所有bean定义信息将要被加载,bean实例还没创建的时候执行,它比BeanFactoryPostProcessor的postProcessBeanFactory()要早。

创建一个MyBeanDefinitionRegistryPostProcessor类,实现BeanDefinitionRegistryPostProcessor接口中的方法。

package com.atguigu.ext;

import com.atguigu.bean.Car;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    /**
     * @param beanDefinitionRegistry bean信息保存中心,后面BeanFactory就是按照BeanDefinitionRegistry里保存的每一个bean定义信息创建Bean实例
     * @throws BeansException
     */
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry...bean的数量:" + beanDefinitionRegistry.getBeanDefinitionCount());
        // 还可以通过beanDefinitionRegistry自己添加bean
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Car.class);
        // 另一种获取BeanDefinition的方式
        // AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Car.class).getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("car", rootBeanDefinition);
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor.postProcessBeanFactory...bean的数量:" + configurableListableBeanFactory.getBeanDefinitionCount());
    }
}

因为BeanDefinitionRegistryPostProcessor在BeanFactoryPostProcessor前执行,所以我们可以利用BeanDefinitionRegistryPostProcessor给容器中添加一些组件。

3.ApplicationListener用法

ApplicationListener可以监听容器中发生的事件,进行事件驱动模型开发。public interface ApplicationListener<E extends ApplicationEvent> extends EventListener可以监听ApplicationListener及其下面的子事件。

创建一个MyApplicationListener实现ApplicationListener接口的方法。

package com.atguigu.ext;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        System.out.println("MyApplicationListener.onApplicationEvent...收到事件" + applicationEvent);
    }
}

发布自定义监听器:

  1. 编写一个监听器来监听事件(ApplicationEvent及其子事件)
  2. 将监听器添加到容器中
  3. 容器中有相关事件发布,监听器就可以监听到事件,现在我们可以监听到ContextRefreshedEvent和ContextClosedEvent
  4. 发布事件

4.ApplicationListener原理

事件发布流程:

调用refresh()方法刷新IOC容器→在refresh()方法最后一步,执行finishRefresh()方法→调用publishEvent方法将事件发布出去→获取事件多播器getApplicationEventMulticaster()并调用multicastEvent()方法进行派发。

public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
    ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
    // 获取所有的ApplicationListener用于遍历
    Iterator var4 = this.getApplicationListeners(event, type).iterator();
    while(var4.hasNext()) {
        final ApplicationListener<?> listener = (ApplicationListener)var4.next();
        Executor executor = this.getTaskExecutor();
        // 可以异步执行,则创建线程异步执行
        if (executor != null) {
            executor.execute(new Runnable() {
                public void run() {
                    SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
                }
            });
        } else {// 同步执行
            this.invokeListener(listener, event);
        }
    }
}

执行invokeListener()方法→执行doInvokeListener()→执行onApplicationEvent()方法。

在refresh()方法中,initApplicationEventMulticaster()方法用于创建事件多播器。

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
    // 查找容器中是否有以applicationEventMulticaster为id的组件,如果有就用它
    if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
        this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    } else {// 如果没有,就自己创建一个SimpleApplicationEventMulticaster类型的多播器组件,并注册进容器,其他组件在派发事件的时候,直接从容器中获取这个多播器即可使用
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [" + this.applicationEventMulticaster + "]");
        }
    }
}

在refresh()方法中,有一个registerListeners()方法,首先获取所有的ApplicationListener,并把它们加到多播器中。

5.@EventListener与SmartInitializingSingleton

@EventListener可以标注在方法上,表示这个方法用来监听事件。

package com.atguigu.ext;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    // 在classes里指定要监听的事件
    @EventListener(classes = {ApplicationEvent.class})
    public void listen(ApplicationEvent applicationEvent) {
        System.out.println("UserService.listen...监听到的事件:" + applicationEvent);
    }
}

@EventListener能起作用,是EventListenerMethodProcessor类来做的处理。EventListenerMethodProcessor实现了SmartInitializingSingleton接口,接口里有一个afterSingletonsInstantiated()方法,afterSingletonsInstantiated()方法会在所有的单实例bean创建完成后执行,通过调试,可以查看调用路径。

refresh()→finishBeanFactoryInitialization()→beanFactory.preInstantiateSingletons()→DefaultListableBeanFactory.preInstantiateSingletons()→smartSingleton.afterSingletonsInstantiated()。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值