• Spring拓展知识:后置处理器与事件监听器


    Spring 拓展

    使ssm的的时候。首先就会找到spring ,为什么?

    应为我们需要将对象交给srping来统一管理,

    我们先来复习一下,spring的两大特性

    ioc

    我们同过spring来帮助我们创建类,帮助我们类之间的解耦

    aop

    可以在不改变类的源码情况下,添加一些增强的方法,可以是前置,后置 ,异常等等

    我们想要用框架,实现越来越多的功能的时候,往往要填加很多很多的bean组件,在使用的时候就可以直接去使用ioc容器中的类,

    后置处理器

    创建类也有区分不同

    • 有工厂创建的单例
    • 有bean的创建

    这些都需要有对应的后置处理器,接下来我们就来看看spring给我们提供了那些灵活的处理器,只要是注入到容器中的bean在即将初始化的时候,都会执行后置处理器,完成之后才放入spring的池子中。

    bean的处理器

    BeanPostProcessor : bean的后置处理器作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下

    源码中有两个方法:

    postProcessBeforeInitialization:实例化,依赖注入完毕,再调用显示初始化之前完成游戏额定制初始化的任务

    postProcessAfterInitialization:实例化,依赖注入,初始化后执行

    这里我们写个小demo来体验一下

    新建一个类,叫myBeanPostProcessor,我们实现这个后置处理器的接口

    参数解释 :

    参数1 bean :就是我们注入到ioc的对象

    参数2 beanName : 就是我们注入到ioc的对象名字

    public class MyBeanPostProcessor implements BeanPostProcessor {
      public Object postProcessBeforeInitialization(Object bean, String beanName)
          throws BeansException {
        System.out.println(beanName+"初始化执行前");
        return bean;
      }
    
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName+"初始化执行后");
        return bean;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    简单实例,实行之后,可以看我们注入对象的初始化前和初始化后的输出信息

    Bean工厂后置处理器

    这个bean工厂处理器,是在所有bean的创造之前对bean的一些修改,我们可以在没有构造对象之前,对bean做什么,

    postProcessBeanFactory方法 : 参数有bean工厂的对象,可以查看到一些信息

    image-20211010172012953

    他就是返回一个在bena创建之前的创建工厂对象,我们可以查看工厂中要创建的bean信息

    BeanDefinitionRegistryPostProcessor(后置bean组件信息处理器)

    为了处理我们在放容器到spring的时候的一些配置,比如是否单例,初始化方法,销毁方法,等等信息的后置处理器

    image-20211010172341715

    方法

    postProcessBeanDefinitionRegistrybean对象的配置信息注册

    postProcessBeanFactory之后进到bean的工厂

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry)
          throws BeansException {
        System.out.println("postProcessBeanDefinitionRegistry:" + beanDefinitionRegistry);
      }
    
      public void postProcessBeanFactory(
          ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("ConfigurableListableBeanFactory:" + configurableListableBeanFactory);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Bean组件的各个生命周期

    • bean组件信息处理器:组件信息注册
    • bean工厂创建,我们自己写的后置工厂处理器是一样的,
    • bean创建和注入完成
    • 初始化前
    • 初始化完成
    • 初始后
    • 销毁

    小demo,使用Bean工厂操作bean的注入

    全新配置文件 : beanFactoryProcessor.xml,就放两个没有任何配置的bean对象

        <bean id="mypostProcessBeanFactory" class="com.hyc.Processor.MypostProcessBeanFactory"/>
        <bean id="demobean" class="com.hyc.springBean.demoBean">bean>
    
    
    • 1
    • 2
    • 3

    用beanFactory操作bean对象,实现配置,和属性注入

    public class MypostProcessBeanFactory implements BeanFactoryPostProcessor {
      public void postProcessBeanFactory(
          ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("configurableListableBeanFactory" + configurableListableBeanFactory);
        // 获取对象
        AbstractBeanDefinition demobean =
            (AbstractBeanDefinition) configurableListableBeanFactory.getBeanDefinition("demobean");
        // 设置初始化方法
        demobean.setInitMethodName("init1");
        // 注入name值
        MutablePropertyValues propertyValues = demobean.getPropertyValues();
        propertyValues.add("name", "PostProcessorFactory bane name");
        // 设置销毁方法
        demobean.setDestroyMethodName("destroy1");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    之后输出查看信息

    image-20211010174808177

    接下来我们复制一个自定义bean工厂

    image-20211010175106616

    配置文件新增一个bean

        
    
    • 1

    给两个工厂实现优先级接口,设置优先级,

    一号工厂优先级为5

    二号工厂优先级为10

    public class MypostProcessBeanFactory2 implements BeanFactoryPostProcessor, Ordered {
     //之前工厂的代码省略
    
      public int getOrder() {
        return 10;
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启动测试

    image-20211010175631070

    可以看到有级别为5的是线执行的

    完美,以上就是用后置处理器来操作bean属性的是实战了

    spring事件监听器

    可以监听我们spring中发生的时间,我们也可以自定义一个spring的事件监听器

    我们学习这个主要是要知道spring在容器中执行的时候都派发了什么事件

    这里我们实现ApplicationListener

    这里泛型里的对象是全局的消息,我们也可以写一个自己的自定义的

    public class MyApplicationEvent extends ApplicationEvent {
      public MyApplicationEvent(Object source) {
        super(source);
      }
    
      String username;
      String emial;
    
      public String getUsername() {
        return username;
      }
    
      public void setUsername(String username) {
        this.username = username;
      }
    
      public String getEmial() {
        return emial;
      }
    
      public void setEmial(String emial) {
        this.emial = emial;
      }
    
      public MyApplicationEvent(Object source, String username, String emial) {
        super(source);
        this.username = username;
        this.emial = emial;
      }
    }
    
    
    • 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

    之后创建新的配置文件 Listener.xml将事件监听器加入到spring容器中

      <bean id="listener" class="com.hyc.listener.myApplicationListener"></bean>
    
    • 1

    修改事件监听器,让我们来看看是在生成bean的时候都派发了什么事件吧

    public class myApplicationListener implements ApplicationListener<ApplicationEvent> {
      public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("接受到的事件" + event);
          //这里怕判断是如果有我们自己的定义内容将事件监听器强转成我们的自定监听器,保证自己的自定义事件也可以输出
        if (event instanceof MyApplicationEvent) {
          MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
          System.out.println("用户名" + myApplicationEvent.getUsername());
          System.out.println("用户邮箱" + myApplicationEvent.getEmial());
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    之后测试

    public class listenerMain {
      public static void main(String[] args) {
        ClassPathXmlApplicationContext ApplicationContext =
            new ClassPathXmlApplicationContext("Listener.xml");
        //创建事件对象
        MyApplicationEvent event = new MyApplicationEvent("事件内容", "james", "123@qq,com");
        //发送事件
        ApplicationContext.publishEvent(event);
        ApplicationContext.close();
        //
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    image-20211010182140609

    可以看到图中spring的加载过程越来越明显清晰了起来

  • 相关阅读:
    获取1688店铺所有商品、店铺列表api
    10.SpringBoot实战演练
    Arm功耗管理精讲与实战
    SpringBoot 如何实现文件上传和下载
    Golang 数组和切片
    深度学习之基于Pytorch服装图像分类识别系统
    Python中的闭包是怎么回事儿?五分钟看懂。
    C++多线程01
    3038. 相同分数的最大操作数目 I(Rust模拟击败100%Rust用户)
    深入聊聊java中判等问题:你真的会用==和equals吗
  • 原文地址:https://blog.csdn.net/doomwatcher/article/details/126875222