目录

spring注解驱动之扩展

BeanFactoryPostProcessor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public interface BeanFactoryPostProcessor {

   /**
    * Modify the application context's internal bean factory after its standard
    * initialization. All bean definitions will have been loaded, but no beans
    * will have been instantiated yet. This allows for overriding or adding
    * properties even to eager-initializing beans.
    * @param beanFactory the bean factory used by the application context
    * @throws org.springframework.beans.BeansException in case of errors
    */
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

与BeanPostProcessor进行比较

  • BeanPostProcessor

    bean后置处理器,bean创建对象初始化前后进行拦截工作的

  • BeanFactoryPostProcessor

    beanFactory的后置处理器;在BeanFactory标准初始化之后调用,来定制和修改BeanFactory的内容;

    标准初始化?所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建

    通俗点说beanFactoryPostProcessor的作用就是在BeanDefinition定义好后可以有个二次修改的机会

演示:

自定义bean实现BeanFactoryPostProcessor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

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

源码分析:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // Prepare this context for refreshing.
      prepareRefresh();

      // Tell the subclass to refresh the internal bean factory.
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // Prepare the bean factory for use in this context.
      prepareBeanFactory(beanFactory);

      try {
         // Allows post-processing of the bean factory in context subclasses.
         postProcessBeanFactory(beanFactory);

        // 会在此处执行BeanFactoryPostProcessor逻辑,在这个点除了工厂类没有其他任何bean被实例化
         // Invoke factory processors registered as beans in the context.
         invokeBeanFactoryPostProcessors(beanFactory);

         // Register bean processors that intercept bean creation.
         registerBeanPostProcessors(beanFactory);

         // Initialize message source for this context.
         initMessageSource();

         // Initialize event multicaster for this context.
         initApplicationEventMulticaster();

         // Initialize other special beans in specific context subclasses.
         onRefresh();

         // Check for listener beans and register them.
         registerListeners();

         // Instantiate all remaining (non-lazy-init) singletons.
         finishBeanFactoryInitialization(beanFactory);

         // Last step: publish corresponding event.
         finishRefresh();
      }
     。。。
   }
}

org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

如何找到所有的BeanFactoryPostProcessor并执行他们的方法

  1. 直接在BeanFactory中找到所有类型是BeanFactoryPostProcessor的组件,并执行他们的方法
  2. 在初始化创建其他组件前面执行

BeanDefinitionRegistryPostProcessor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

   /**
    * Modify the application context's internal bean definition registry after its
    * standard initialization. All regular bean definitions will have been loaded,
    * but no beans will have been instantiated yet. This allows for adding further
    * bean definitions before the next post-processing phase kicks in.
    * @param registry the bean definition registry used by the application context
    * @throws org.springframework.beans.BeansException in case of errors
    */
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

说明:

  • 在所有bean定义信息将要被加载,bean实例还未创建时调用;所以会在BeanFactoryPostProcessor之前执行
  • 可以利用BeanDefinitionRegistryPostProcessor给容器中再额外添加一些组件

演示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.eh.ext;

import com.eh.bean.Red;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

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

    //BeanDefinitionRegistry Bean定义信息的保存中心,以后BeanFactory就是按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例;
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("postProcessBeanDefinitionRegistry...bean的数量:" + registry.getBeanDefinitionCount());
        //RootBeanDefinition beanDefinition = new RootBeanDefinition(Blue.class);
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Red.class).getBeanDefinition();
        registry.registerBeanDefinition("hello", beanDefinition);
    }

}

源码分析:

1
2
3
4
5
6
7
1)、ioc创建对象
2)、refresh()-invokeBeanFactoryPostProcessors(beanFactory);
3)、从容器中获取到所有的BeanDefinitionRegistryPostProcessor组件
   1依次触发所有的postProcessBeanDefinitionRegistry()方法
   2再来触发postProcessBeanFactory()方法BeanFactoryPostProcessor

4)、再来从容器中找到BeanFactoryPostProcessor组件然后依次触发postProcessBeanFactory()方法

ApplicationListener

监听容器中发布的事件;事件驱动模型开发;监听 ApplicationEvent 及其下面的子事件;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

   /**
    * Handle an application event.
    * @param event the event to respond to
    */
   void onApplicationEvent(E event);

}

ApplicationListener的使用

  1. 写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    
    package com.eh.ext;
       
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.stereotype.Component;
       
    @Component
    public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
       
        //当容器中发布此事件以后,方法触发
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            System.out.println("收到事件:" + event);
        }
       
    }
    
  2. 把监听器加入到容器

  3. 只要容器中有相关事件的发布,我们就能监听到这个事件;

    • ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件;
    • ContextClosedEvent:关闭容器会发布这个事件;
  4. 发布一个事件

    1
    2
    3
    4
    5
    6
    7
    
    public static void main(String[] args) {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ExtConfig.class);
            //发布事件;
            applicationContext.publishEvent(new ApplicationEvent("发布事件") {
            });
            applicationContext.close();
        }
    
  5. 测试结果

    1
    2
    3
    
    收到事件org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3891771e, started on Sat Oct 31 12:34:33 CST 2020]
    收到事件com.eh.MainTest$1[source=发布事件]
    收到事件org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3891771e, started on Sat Oct 31 12:34:33 CST 2020]
    

原理:

以ContextRefreshedEvent为例

事件发布流程

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
onApplicationEvent:13, MyApplicationListener (com.eh.ext)
doInvokeListener:172, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
publishEvent:404, AbstractApplicationContext (org.springframework.context.support)
publishEvent:361, AbstractApplicationContext (org.springframework.context.support)
// 容器刷新完成会发布ContextRefreshedEvent事件
finishRefresh:898, AbstractApplicationContext (org.springframework.context.support)
refresh:554, AbstractApplicationContext (org.springframework.context.support)
<init>:89, AnnotationConfigApplicationContext (org.springframework.context.annotation)
main:15, MainTest (com.eh)
  1. publishEvent(new ContextRefreshedEvent(this));

  2. 获取事件的多播器(派发器):getApplicationEventMulticaster()

  3. multicastEvent派发事件

  4. 获取到所有的ApplicationListener;

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
       ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
      // 如果有Executor,可以支持使用Executor进行异步派发;
       Executor executor = getTaskExecutor();
       for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          if (executor != null) {
             executor.execute(() -> invokeListener(listener, event));
          }
          else {
            // 否则,同步的方式直接执行listener方法;
            // 拿到listener回调onApplicationEvent方法
             invokeListener(listener, event);
          }
       }
    }
    

事件派发器

1
2
3
4
5
1)、容器创建对象refresh();
   2)、initApplicationEventMulticaster();初始化ApplicationEventMulticaster
      1)、先去容器中找有没有id=applicationEventMulticaster的组件
      2)、如果没有this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
         并且加入到容器中我们就可以在其他组件要派发事件自动注入这个applicationEventMulticaster

容器中有哪些监听器

1
2
3
4
5
6
1)、容器创建对象refresh();
   2)、registerListeners();
      从容器中拿到所有的监听器把他们注册到applicationEventMulticaster中
      String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
      //将listener注册到ApplicationEventMulticaster中
      getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);

@EventListener

事件监听除了实现ApplicationListener外还可以使用注解@EventListener进行实现

注解定义:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/**
...
<p>Processing of {@code @EventListener} annotations is performed via
注解处理器 EventListenerMethodProcessor
 * the internal {@link EventListenerMethodProcessor} bean which gets
 ...
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {

   @AliasFor("classes")
   Class<?>[] value() default {};

   @AliasFor("value")
   Class<?>[] classes() default {};

   String condition() default "";

}

注解使用:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Service
public class BookService {

    @EventListener(classes = {ApplicationEvent.class})
    public void listen(ApplicationEvent event) { // 使用方法参数接受事件
        System.out.println("BookService监听到的事件:" + event);
    }
}

// 运行结果:
BookService监听到的事件org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3891771e, started on Sat Oct 31 12:59:10 CST 2020]
BookService监听到的事件com.eh.MainTest$1[source=发布事件]
BookService监听到的事件org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@3891771e, started on Sat Oct 31 12:59:10 CST 2020]

原理:

使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;

1
2
public class EventListenerMethodProcessor
      implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {

EventListenerMethodProcessor实现了SmartInitializingSingleton接口的afterSingletonsInstantiated方法,

在这个方法中将使用有@EventListener注解的方法转成一个ApplicationListenerBean并且注入到容器中

1
2
3
4
5
6
ApplicationListener<?> applicationListener =
      factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
   ((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
context.addApplicationListener(applicationListener);

之后与MyApplicationListener一样,在调用publishEvent的时候触发回调

afterSingletonsInstantiated方法执行时机

1
2
3
4
5
1)、ioc容器创建对象并refresh()
2)、finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean
   1)、先创建所有的单实例beangetBean();
   2)、获取所有创建好的单实例bean判断是否是SmartInitializingSingleton类型的
      如果是就调用afterSingletonsInstantiated();

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

  1. 先创建所有的单实例bean;getBean();
  2. 获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;如果是就调用afterSingletonsInstantiated();
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public void preInstantiateSingletons() throws BeansException {
   if (logger.isTraceEnabled()) {
      logger.trace("Pre-instantiating singletons in " + this);
   }

   // Iterate over a copy to allow for init methods which in turn register new bean definitions.
   // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
   List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

   // Trigger initialization of all non-lazy singleton beans...
  // 先创建所有的单实例bean;getBean();
   for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
         if (isFactoryBean(beanName)) {
            Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
            if (bean instanceof FactoryBean) {
               FactoryBean<?> factory = (FactoryBean<?>) bean;
               boolean isEagerInit;
               if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                  isEagerInit = AccessController.doPrivileged(
                        (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
                        getAccessControlContext());
               }
               else {
                  isEagerInit = (factory instanceof SmartFactoryBean &&
                        ((SmartFactoryBean<?>) factory).isEagerInit());
               }
               if (isEagerInit) {
                  getBean(beanName);
               }
            }
         }
         else {
            getBean(beanName);
         }
      }
   }

   // Trigger post-initialization callback for all applicable beans...
   for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
     // 获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;如果是就调用afterSingletonsInstantiated();
      if (singletonInstance instanceof SmartInitializingSingleton) {
         SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
         if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
               smartSingleton.afterSingletonsInstantiated();
               return null;
            }, getAccessControlContext());
         }
         else {
           // 调用如果是就调用afterSingletonsInstantiated
            smartSingleton.afterSingletonsInstantiated();
         }
      }
   }
}