我随意写,你随意看。

林老头儿

但愿绝望和无奈远走高飞

Fork me on Gitee

Spring注解驱动开发6:Spring扩展原理

Spring注解驱动开发系列:

  1. Spring注解驱动开发1:组件注册
  2. Spring注解驱动开发2:生命周期和属性赋值
  3. Spring注解驱动开发3:自动装配
  4. Spring注解驱动开发4:AOP使用和原理
  5. Spring注解驱动开发5:Spring声明式事务
  6. Spring注解驱动开发6:Spring扩展原理

Spring注解驱动开发6:Spring扩展原理

BeanFactoryPostProcessor

例子

编写MyBeanFactoryPostProcessor类如下:

@Repository
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor....invoke");
        int beanDefinitionCount = beanFactory.getBeanDefinitionCount();
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        System.out.println("总共有:" + beanDefinitionCount);
        System.out.println("分别是:");
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }
    }
}

编写配置类代码如下:

//配置类==配置文件
@Configuration
//开启自动包扫描,传入要扫描的包路径
@ComponentScan(basePackages = "com.lin.springL")
public class MainConfigure {

}

编写测试类代码如下:

public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(MainConfigure.class);
    }
}

运行得到结果:

MyBeanFactoryPostProcessor....invoke
总共有:8
分别是:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfigure
myBeanFactoryPostProcessor

在容器初始化的时候就会执行,具体执行过程可以查看我的Spring源码篇。

唯一要关注的是,执行BeanFactoryPostProcessor的时候,这时候BeanFactory只有Bean的定义BeanDefinition,还没有初始化Bean。

具体调用链,可以通过Debug直接查看:

image-20200519234906988

最终的具体细节就是对所有的BeanFactoryPostProcessor遍历执行:

private static void invokeBeanFactoryPostProcessors(
      Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

   for (BeanFactoryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanFactory(beanFactory);
   }
}

BeanDefinitionRegistryPostProcessor

Bean定义信息注册器的后置处理器,实现了BeanFactoryPostProcessor接口,与其不同的是:

  • BeanFactoryPostProcessor是在Bean的定义信息加载完后执行,而BeanDefinitionRegistryPostProcessor是在bean定义信息正要加载的时候执行。

例子

编写MyBeanDefinitionRegistryPostProcessor类:

@Repository
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor----postProcessBeanDefinitionRegistry");
        //可以在这里创建自己的BeanDefinition
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Lin.class);
        registry.registerBeanDefinition("lin", rootBeanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor----postProcessBeanFactory");
    }
}

更改MainTest如下:

public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(MainConfigure.class);
        Lin bean = applicationContext.getBean(Lin.class);
        System.out.println(bean);
    }
}

运行得到结果:

MyBeanDefinitionRegistryPostProcessor----postProcessBeanDefinitionRegistry
MyBeanDefinitionRegistryPostProcessor----postProcessBeanFactory
MyBeanFactoryPostProcessor....invoke
com.lin.springL.pojo.Lin@166fa74d

可以看到MyBeanDefinitionRegistryPostProcessor先于MyBeanFactoryPostProcessor执行。

BeanFactory就是根据BeanDefinitionRegistry所定义的BeanDefinition来创建对应的Bean实例。因此在此可以通过registry.registerBeanDefinition("lin", rootBeanDefinition);来注册自定义的Bean定义,之后就会被BeanFactory初始化。

private static void invokeBeanDefinitionRegistryPostProcessors(
      Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

   for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
      postProcessor.postProcessBeanDefinitionRegistry(registry);
   }
}

ApplicationListener

监听容器中发布的事件,完成事件驱动模型的开发。

例子

编写MyApplicationListener类如下:

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    //当容器中发布此事件后,方法触发
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("收到事件:" + event);
    }
}

编写MainTest类代码如下:

public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(MainConfigure.class);
        applicationContext.close();
    }
}

运行得到如下输出:

收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:02:43 CST 2020]; root of context hierarchy]
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:02:43 CST 2020]; root of context hierarchy]

可以看到容器的启动和关闭事件都被监听到了,因此可以监听ApplicationEvent及其子类的事件,所以如果需要自定义事件,继承ApplicationEvent后由Spring发布消息,然后就可以在ApplicationListener进行监听操作了。

自定义发布事件

更改MainTest代码如下:

public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(MainConfigure.class);
        applicationContext.publishEvent(new ApplicationEvent(new String("自定义事件")) {
        });
        applicationContext.close();
    }
}

执行得到输出:

收到事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:10:32 CST 2020]; root of context hierarchy]
收到事件:com.lin.springL.MainTest$1[source=自定义事件]
收到事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:10:32 CST 2020]; root of context hierarchy]

我们发布的消息也成功被监听到。

@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      Executor executor = getTaskExecutor();
      if (executor != null) {
         executor.execute(new Runnable() {
            @Override
            public void run() {
               invokeListener(listener, event);
            }
         });
      }
      else {
         invokeListener(listener, event);
      }
   }
}

@EventListener

上面实现监听需要自己定义类实现ApplicationListener,在这里可以使用注解的方式,让任意一个方法成为监听方法。

例子

编写UserService类如下:

@Service
public class UserService {
    //监听ApplicationEvent事件
    @EventListener(classes = {ApplicationEvent.class})
    public void listener(ApplicationEvent event) {
        System.out.println("UserService监听事件:" + event);
    }
}

编写配置类如下:

//配置类==配置文件
@Configuration
//开启自动包扫描,传入要扫描的包路径
@ComponentScan(basePackages = "com.lin.springL")
public class MainConfigure {

}

编写MainTest类如下:

public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new
                AnnotationConfigApplicationContext(MainConfigure.class);
        applicationContext.publishEvent(new ApplicationEvent(new String("自定义事件")) {
        });
        applicationContext.close();
    }
}

运行得到输出:

UserService监听事件:org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:51:57 CST 2020]; root of context hierarchy]
UserService监听事件:com.lin.springL.MainTest$1[source=自定义事件]
UserService监听事件:org.springframework.context.event.ContextClosedEvent[source=org.springframework.context.annotation.AnnotationConfigApplicationContext@21b8d17c: startup date [Wed May 20 10:51:57 CST 2020]; root of context hierarchy]

可以看到也是可以监听到事件。

posted @ 2020-05-20 11:07  林老头儿  阅读(230)  评论(0编辑  收藏  举报