ApplicationListener与ApplicationContextAware

一、ApplicationContextAware

Spring定义的类实现ApplicationContextAware接口会自动的将应用程序上下文加入,首先我们看下具体的实现示例:

1、示例代码

@Component
public class SpringContextHolder implements ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextHolder.applicationContext = applicationContext;
    }
}

2、ApplicationContextAware的使用方式很简单,只要实现接口重写方法就可以,下面我们看下应用程序是如何初始化的

AbstractApplicationContext类是Spring容器应用上下文的一个抽象父类,我们看下里面的prepareBeanFactory方法

  protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.setBeanClassLoader(this.getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
        //添加ApplicationContextAware的处理器
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
        beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
        if (beanFactory.containsBean("loadTimeWeaver")) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        if (!beanFactory.containsLocalBean("environment")) {
            beanFactory.registerSingleton("environment", this.getEnvironment());
        }

        if (!beanFactory.containsLocalBean("systemProperties")) {
            beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
        }

        if (!beanFactory.containsLocalBean("systemEnvironment")) {
            beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
        }

    }

3、进入ApplicationContextAwareProcessor处理器类查看代码

    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
        if (System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(() -> {
                //调用ApplicationContextAware 初始化方法
                this.invokeAwareInterfaces(bean);
                return null;
            }, acc);
        } else {
            this.invokeAwareInterfaces(bean);
        }

        return bean;
    }
    //具体实现
   private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
            }

            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }

            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
            }

            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
            }

            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
            }
            //初始化
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
            }
        }

    }

通过上面的代码可以很清楚的了解到ApplicationContextAware实现类在应用启动的时候就会初始化。。。

二、ApplicationListener

1、知识点

1)ApplicationListener接口

该接口继承了java.util.EventListener接口

public interface ApplicationListener extends EventListener {
    void onApplicationEvent(E event);
}

可以看到,只有一个方法onApplicationEvent,我们在自定义得时候,只需要实现这个接口,并且实现onApplicationEvent方法,在方法编写被触发的时候,需要进行处理的业务逻辑

注意:该接口的实现类必须放到IOC容器中,否者是不会起作用的

2)ApplicationEvent抽象类

该类定义了事件类型,每个监听器可以通过泛型来设置对某一种或者几种的事件在发生时有反应,作用主要是来进行分类,或者在listener关注的EventObject发生时,可以通过EventObject来向listener传递一些参数,例如事件发生的时间,当时的上下文情况等,可以根据需要重写自己的EventObject类。自定义类型的时候,需要继承该抽象类,并且实现自己的逻辑即可。

Spring中有很多已经实现了的listener

注意:所有的spring事件类型均需要继承该抽象类。

Spring部分内置事件

a、ContextRefreshedEvent

ApplicationContext 被初始化或刷新时,该事件被触发。这也可以在ConfigurableApplicationContext接口中使用 refresh() 方法来触发。

b、ContextStartedEvent

当使用 AbstractApplicationContext(ApplicationContext子接口)中的 start() 方法启动 ApplicationContext 时,该事件被发布。可以在listener中做一些初始化的操作

c、ContextStoppedEvent

当使用AbstractApplicationContex中的stop()停止ApplicationContext 时,发布这个事件。可以在listener进行释放资源的操作。

d、ContextClosedEvent

当使用 AbstractApplicationContext接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。

3)ApplicationEventMulticaster

该接口定义了如何去管理和发布事件

public interface ApplicationEventMulticaster {
    void addApplicationListener(ApplicationListener var1);

    void addApplicationListenerBean(String var1);

    void removeApplicationListener(ApplicationListener var1);

    void removeApplicationListenerBean(String var1);

    void removeAllListeners();

    void multicastEvent(ApplicationEvent var1);

    void multicastEvent(ApplicationEvent var1, ResolvableType var2);
}

其下有很多实现类,spring主要使用了其中的SimpleApplicationEventMulticaster

2、代码示例

1)内置Event

a、编写需要监听的listener

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.stereotype.Component;
/**
 * 1.实现ApplicationListener,并且传入需要关注的事件类型,如果不传的话,所有的事件在触发时都会被触发
 * 2.实现onApplicationEvent方法,可以通过event来获取数据
 * 3.将其注入到容器中,此处实现@Component
 */
@Component
public class MyStopListener implements ApplicationListener{
    @Override
    public void onApplicationEvent(ContextStoppedEvent event) {
        System.out.println("IOC容器执行了stop方法...........");
    }
}

b、测试

public class ListenerTest {
    @Test
    public void testNotifyListener() {
        ApplicationContext ctx=new AnnotationConfigApplicationContext(MyConfig.class);
        ((AbstractApplicationContext) ctx).stop();
    }
}

2)自定义Event

a、自定义Event

public class NotifyEvent extends ApplicationContextEvent{

    private String caller;

    public NotifyEvent(ApplicationContext source,String caller) {

        super(source);

        this.caller=caller;

    }

    public String getCaller() {

        return caller;

    }
    private static final long serialVersionUID = 1L;
}

b、listener

@Component
public class NotifyUserListener implements ApplicationListener{
    @Override
    public void onApplicationEvent(NotifyEvent event) {
        String caller=event.getCaller();
        System.out.println(caller+"来叫大家干活了.......");
    }
}

c、测试

@Test
public void testNotifyListener() {
    ApplicationContext ctx=new AnnotationConfigApplicationContext(MyConfig.class);
    String caller="马云";
    ctx.publishEvent(new NotifyEvent(ctx, caller));
}

仅用于个人记录学习

参考链接:https://blog.csdn.net/yxLearnJava/article/details/106179848

你可能感兴趣的:(JAVA基础,前端,java,spring)