Spring的ApplicationEvent

為{幸葍}努か 提交于 2020-02-20 14:18:12

最近项目用到了observer观察者模式:
event,listener是observer模式一种体现,这里我们介绍ApplicationEvent的使用。
一.PropertyAddedEvent继承ApplicationEvent
在这里插入图片描述二.监听类PropertyEventHandler在这里插入图片描述
BookingEventsListener 需要实现ApplicationListener 并重写onApplicationEvent方法***。ApplicationListener带泛型,如果泛型参数为BookingCreatedEvent,则表示只监听BookingCreatedEvent类型的事件,如果泛型参数为ApplicationEvent ,则表示监听所有类型的事件。***另外可以用@Component来注册组件,这样就不需要在spring的配置文件中指定了。
触发要实现ApplicationContextAware,用于引入ApplicationContext,由于bookingService也 是spring组件,所以在系统启动的时候,ApplicationContext已经注入。也可以用如下方式直接注入 ApplicationContext。

三.触发event
在这里插入图片描述
原理:
首先说说spring的IOC容器初始化过程,首先Spring会定位BeanDefinition资源文件,然后会一个一个的去加载所有BeanDefinition,这里的BeanDefinition就是指的Bean的资源文件,即:在XML中配置的Bean和通过注解装配的Bean,在加载完所有BeanDefinition之后,会将这些BeanDefinition注册到一个HashMap中。到此spring的IOC初始化完成,那么依赖注入发生在哪里呢?在用户第一次向IOC容器索要Bean时才开始依赖注入过程(也可以通过配置lazy-init属性让容器初始化的时候就对Bean预实例化)

可以看到在Bean所有的属性都被注入之后会去调用这个afterPropertiesSet()方法,其实在依赖注入完成的时候,spring会去检查这个类是否实现了InitializingBean接口,如果实现了InitializingBean接口,就会去调用这个类的afterPropertiesSet()方法。所以afterPropertiesSet()方法的执行时间点就很清楚了,发生在所有的properties被注入后

package com.purcotton.omni.download.config;

import com.purcotton.omni.download.core.OrderType;
import com.purcotton.omni.download.core.PageSynchronizer;
import com.purcotton.omni.download.core.StreamSynchronizer;
import com.purcotton.omni.sync.SyncProperty;
import lombok.SneakyThrows;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.stereotype.Component;

import static org.springframework.util.ObjectUtils.isEmpty;

@Component
public class PropertyEventHandler implements ApplicationContextAware, ApplicationListener<PropertyAddedEvent> {

    private GenericApplicationContext applicationContext;

    @Override
    public void onApplicationEvent(PropertyAddedEvent event) {
        SyncProperty property = (SyncProperty) event.getSource();
        String beanName = property.getId() + "Synchronizer";

        BeanDefinitionBuilder builder;
        if (property.getVersion() >= 2.0) {
            builder = BeanDefinitionBuilder
                    .genericBeanDefinition(property.getPullStrategy().equalsIgnoreCase("page") ?
                            PageSynchronizer.class : StreamSynchronizer.class)
                    .addConstructorArgValue(property)
                    .addPropertyReference("formatter", "formatter")
                    .addPropertyReference("scheduleMapper", "syncScheduleMapper")
                    .addPropertyReference("errorMapper", "syncErrorMapper")
                    .addPropertyReference("restTemplate", property.isLoadBalanced()
                            ? "loadBalancedRestTemplate" : "sslRestTemplate")
                    .addPropertyReference("dataStorage",
                            isEmpty(property.getStorageService()) ? "mapDataStorage" : "codeDataStorage");
        } else {
            builder = BeanDefinitionBuilder
                    .genericBeanDefinition(getBeanClass(property));
            if (!isEmpty(property.getType())) {
                builder.addConstructorArgValue(OrderType.valueOf(property.getType()));
            }
            if (!isEmpty(property.getShopCode())) {
                builder.addConstructorArgValue(property.getShopCode());
            }
        }

        synchronized (this) {
            if (!applicationContext.isBeanNameInUse(beanName)) {
                applicationContext.registerBeanDefinition(beanName, builder.getBeanDefinition());
            }
        }
    }

    @SneakyThrows
    private Class<?> getBeanClass(SyncProperty property) {
        String packageName = "com.purcotton.omni.download.core.page";
        String channel = property.getChannel().toLowerCase();

        String className = channel.substring(0, 1).toUpperCase()
                + channel.substring(1) + "Synchronizer";
        return Class.forName(packageName + "." + className);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (GenericApplicationContext) applicationContext;
    }
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!