国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Learn Spring - Spring IoC

luzhuqun / 1360人閱讀

摘要:事件事件監聽器,對監聽到的事件進行處理。擁有一個成員變量,提供了容器監聽器的注冊表。注冊事件監聽器根據反射機制,使用的方法,從中找出所有實現的,將它們注冊為容器的事件監聽器,實際的操作就是將其添加到事件廣播器所提供的監聽器注冊表中。

1. Spring的資源抽象接口

假如有一個文件位于Web應用的類路徑下,用戶可以通過以下方式對這個文件資源進行訪問:

通過FileSystemResource以文件系統絕對路徑的方式進行訪問;

通過ClassPathResource以類路徑的方式進行訪問;

通過ServletContextResource以相對于Web應用根目錄的方式進行訪問。

2. BeanFactory的類體系結構

BeanFactory:位于類結構樹的頂端,最主要的方法是getBean(String beanName),從容器中返回特定類型的bean

ListableBeanFactory:該接口定義了訪問容器中Bean基本信息的若干方法

HierarchicalBeanFactory:父子級聯IoC容器的接口,子容器可以通過接口方法訪問父容器

ConfigurableBeanFactory:增強了IoC容器的可定制性

AutowireCapableBeanFactory:定義了將容器中的bean按照某種規則進行自動裝配的方法

SingletonBeanRegistry:定義了允許在運行期向容器注冊單實例bean的方法

BeanDefinitionRegistry:每一個bean在容器中通過BeanDefinition對象表示,BeanDefinitionRegistry定義了向容器手工注冊bean的方法

Spring在DefaultSingletonBeanRegistry類中提供了一個用于緩存單實例bean的緩存器,以HashMap實現,單實例的bean以beanName為key保存在這個HashMap

3. ApplicationContext的類體系結構

ApplicationEventPublisher:讓容器擁有發布應用上下文事件的功能,包括容器啟動事件、關閉事件等。實現了ApplicationListener事件監聽接口的Bean 可以接收到容器事件,并對事件進行響應處理。在ApplicationContext抽象實現類AbstractApplicationContext中,我們可以發現存在一個ApplicationEventMulticaster,它負責保存所有監聽器,以便在容器產生上下文事件時通知這些事件監聽者。

MessageSource:為應用提供i18n國際化消息訪問的功能;

ResourcePatternResolver:所有ApplicationContext實現類都實現了類似于PathMatchingResourcePatternResolver的功能,可以通過帶前綴的Ant風格的資源文件路徑裝載Spring的配置文件。

LifeCycle:該接口是Spring 2.0加入的,該接口提供了start()stop()兩個方法,主要用于控制異步處理過程。在具體使用時,該接口同時被ApplicationContext實現及具體Bean實現,ApplicationContext會將start/stop的信息傳遞給容器中所有實現了該接口的Bean,以達到管理和控制JMX、任務調度等目的。

ConfigurableApplicationContext擴展于ApplicationContext,它新增加了兩個主要的方法:refresh()close(),讓ApplicationContext具有啟動、刷新和關閉應用上下文的能力。在應用上下文關閉的情況下調用refresh()即可啟動應用上下文,在已經啟動的狀態下,調用refresh()則清除緩存并重新裝載配置信息,而調用close()則可關閉應用上下文。

4. WebApplicantContext體系結構

它允許從相對于Web根目錄的路徑中加載配置文件完成初始化工作。從WebApplicationContext中可以獲取ServletContext引用,整個Web應用上下文對象將作為屬性放置在ServletContext中,以便Web應用環境可以訪問spring上下文。

WebApplicationContext擴展了ApplicationContextWebApplicationContext定義了一個常量ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在上下文啟動時,我們可以直接通過下面的語句從web容器中獲取WebApplicationContext:

WebApplicationContext wac=(WebApplicationContext)servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
5. BeanFactory中Bean的生命周期 5.1 Bean生命周期

如果容器注冊InstantiationAwareBeanPostProcessor接口,調用postProcessBeforeInstantiation方法

Bean的實例化(調用默認構造器)

如果容器注冊InstantiationAwareBeanPostProcessor接口,調用postProcessAfterInstantiation方法

如果容器注冊InstantiationAwareBeanPostProcessor接口,調用postProcessPropertyValues方法

根據配置設置屬性值

如果Bean實現了BeanNameAware接口,調用BeanNameAware接口的setBeanName方法

如果Bean實現了BeanFactoryAware接口,調用BeanFactoryAware接口的setBeanFactory方法

如果容器注冊了BeanPostProcessor接口,調用BeanPostProcessor接口的postProcessBeforeInitialization方法

如果Bean實現了InitializingBean接口,調用InitializingBean接口的afterPropertiesSet方法

通過init-method屬性配置的初始方法

如果容器注冊了BeanPostProcessor接口,調用BeanPostProcessor接口的postProcessAfterInitialization方法

如果是單例模式,將Bean放入緩存池中;容器銷毀時,調用DisposableBean的destroy方法;最后調用destroy-method方法

如果是多例模式,將Bean交給調用者。

5.2 初始化過程中的方法分類

bean自身的方法:如調用bean構造函數實例化bean,調用Setter設置bean的屬性值,以及通過init-methoddestory-method所指定的方法;

bean級生命周期接口方法:如BeanNameAware、BeanFactoryAwareInitializingBeanDisposableBean,這些接口方法由bean類直接實現;

容器級生命周期接口方法:如InstantiationAwareBeanPostProcessorBeanPostProcessor這兩個接口實現,一般稱它們的實現類為“后處理器”。

5.3 說明

Spring的AOP等功能即通過BeanPostProcessor實現

如果通過init-method屬性定義了初始化方法,將執行這個方法

如果bean的作用范圍為scope="prototype",將bean返回給調用者之后,調用者負責bean的后續生命的管理,Spring不再管理這個bean的生命周期;如果scope="singleton",則將bean放入到Spring IoC容器的緩存池中,并將bean的引用返回給調用者,Spring繼續管理這些bean的后續生命周期

對于單例的bean,當容器關閉時,將觸發Spring對bean的后續生命周期的管理工作。如果bean實現了DisposableBean接口,則將調用接口的destroy()方法

對于單例的bean,如果通過destroy-method指定了bean的銷毀方法,Spring將執行這個方法

后處理器的實際調用順序和注冊順序無關,在具有多個后處理器的情況下,必須通過實現org.springframework.core.Ordered接口確定調用順序

5.4 測試

applicationContext.xml




    

Car

package com.data;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class Car implements BeanNameAware, BeanFactoryAware,
    InitializingBean, DisposableBean {

    public Car() {
        System.out.println("construct car");
    }

    private String name;

    private String color;

    private BeanFactory beanFactory;

    private String beanName;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
        System.out.println("set color=" + color);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("after properties set method");
    }

    public void init() {
        System.out.println("init method");
    }

    @Override
    public void destroy() {
        System.out.println("destroy method");
    }

    public void destroy2() {
        System.out.println("my destroy method");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("set bean factory");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("set bean name");
        this.beanName = name;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public String getBeanName() {
        return beanName;
    }
}

MyBeanPostProcessor

package com.beanfactory;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;

public class MyBeanPostProcessor
    extends InstantiationAwareBeanPostProcessorAdapter{

    public MyBeanPostProcessor() {
        System.out.println("construct MyBeanPostProcessor");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        System.out.println("post process before instantiation");
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("post process after instantiation");
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(
    PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("post process property values");
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post process before initialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("post process after initialization");
        return bean;
    }
}

TestBeanFactory

package config;

import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.beanfactory.MyBeanPostProcessor;
import com.data.Car;

@SuppressWarnings("deprecation")
public class TestBeanFactory {

    public static void main(String[] args) {
        Resource res = new ClassPathResource(
                "/applicationContext.xml");
        XmlBeanFactory bf = new XmlBeanFactory(res);
        bf.addBeanPostProcessor(new MyBeanPostProcessor());
        System.out.println("bean factory initialization done");
        Car car1 = bf.getBean("car", Car.class);
        Car car2 = bf.getBean("car", Car.class);
        System.out.println("(car1 == car2) = " + (car1 == car2));
        System.out.println("get color=" + car1.getColor());
        bf.destroySingletons();
    }
}

結果

二月 09, 2017 10:58:59 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [applicationContext.xml]
construct MyBeanPostProcessor
bean factory initialization done
post process before instantiation
construct car
post process after instantiation
post process property values
set color=color
set bean name
set bean factory
post process before initialization
after properties set method
init method
post process after initialization
(car1 == car2) = true
get color=color
destroy method
my destroy method
6. ApplicationContext中的Bean生命周期 6.1 流程圖

6.2 說明

如果bean實現了org.springframework.context.ApplicationContextAware接口,會增加一個調用該接口方法setApplicationContext()的步驟

如果配置文件中聲明了工廠后處理器接口BeanFactoryPostProcessor的實現類,則應用上下文在加載配置文件之后、初始化bean實例之前將調用這些BeanFactoryPostProcessor對配置信息進行加工處理

ApplicationContextBeanFactory的不同之處在于:前者會利用Java反射機制自動識別出配置文件中定義的BeanPostProcessor、InstantiationAwareBeanPostProcessorBeanFactoryPostProcessor,并自動將它們注冊到應用上下文中;而后者需要在代碼中通過手工調用addBeanPostProcessor()方法進行注冊

對bean的初始化,BeanFactory發生在第一次調用bean時,而ApplicationContext發生在初始化容器時

6.3 測試

MyBeanPostProcessor同上

Car增加對ApplicationContextAware接口的實現,并添加@PostConstruct@PreDestroy的注解方法

package com.data;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Car implements BeanNameAware, BeanFactoryAware,
    InitializingBean, DisposableBean, ApplicationContextAware {

    public Car() {
        System.out.println("construct car");
    }

    private String name;

    private String color;

    private BeanFactory beanFactory;

    private String beanName;

    private ApplicationContext ctx;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("after properties set method");
    }

    public void init() {
        System.out.println("init method");
    }

    @Override
    public void destroy() {
        System.out.println("destroy method");
    }

    public void destroy2() {
        System.out.println("my destroy method");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("set bean factory");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("set bean name");
        this.beanName = name;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    public String getBeanName() {
        return beanName;
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("post construct");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("pre destroy");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        System.out.println("set application context");
        this.ctx = applicationContext;
    }

    public ApplicationContext getApplicationContext() {
        return ctx;
    }

}

MyBeanFactoryPostProcessor

package com.beanfactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public MyBeanFactoryPostProcessor() {
        System.out.println("construct MyBeanFactoryPostProcessor");
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("post process bean factory");
    }
}

基于Java類的Spring配置:AnnotationBeans

package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.beanfactory.MyBeanFactoryPostProcessor;
import com.beanfactory.MyBeanPostProcessor;
import com.data.Car;

@Configuration
public class AnnotationBeans {

    @Bean(name = "car", initMethod = "init", destroyMethod = "destroy2")
    public Car getCar() {
        Car car = new Car();
        car.setColor("color");
        return car;
    }

    @Bean(name = "myBeanPostProcessor")
    public MyBeanPostProcessor getMyBeanPostProcessor() {
        return new MyBeanPostProcessor();
    }

    @Bean(name = "myBeanFactoryPostProcessor")
    public MyBeanFactoryPostProcessor getMyBeanFactoryPostProcessor() {
        return new MyBeanFactoryPostProcessor();
    }
}

TestApplicationContext

package config;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.data.Car;

public class TestApplicationContext {

    public static void main(String[] args) {
        /*對于以xml形式初始化的ctx,也可以用ClassPathXmlApplicationContext
        或者FileSystemXmlApplicationContext*/
        AnnotationConfigApplicationContext ctx =
                new AnnotationConfigApplicationContext(
                        AnnotationBeans.class);
        System.out.println("application context done");
        Car car = ctx.getBean("car", Car.class);
        System.out.println("get color=" + car.getColor());
        ctx.close();
    }
}

結果

二月 09, 2017 11:55:25 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@306a30c7: startup date [Thu Feb 09 23:55:25 CST 2017]; root of context hierarchy
二月 09, 2017 11:55:25 下午 org.springframework.context.annotation.ConfigurationClassEnhancer intercept
警告: @Bean method AnnotationBeans.getMyBeanFactoryPostProcessor is non-static and returns an object assignable to Spring"s BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method"s declaring @Configuration class. Add the "static" modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
construct MyBeanFactoryPostProcessor
post process bean factory
construct MyBeanPostProcessor
post process before instantiation
post process after instantiation
post process property values
post process before initialization
post process after initialization
post process before instantiation
post process after instantiation
post process property values
post process before initialization
post process after initialization
post process before instantiation
construct car
post process after instantiation
post process property values
set bean name
set bean factory
set application context
post process before initialization
post construct
after properties set method
init method
post process after initialization
application context done
get color=color
二月 09, 2017 11:55:25 下午 org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
信息: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@306a30c7: startup date [Thu Feb 09 23:55:25 CST 2017]; root of context hierarchy
pre destroy
destroy method
my destroy method
7. 容器內部工作機制 7.1 啟動源碼

Spring的AbstractApplicationContext的refresh()方法定義了Spring容器在加載配置文件后的各項處理工作

@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);

            // 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();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context initialization - " +
            "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset "active" flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
        // Reset common introspection caches in Spring"s core, since we
        // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}
7.2 容器啟動流程

ContextLoaderListener通過調用繼承自ContextLoaderinitWebApplicationContext方法實例化SpringIoC容器。在實例化Spring IoC容器的過程中,最主要的兩個方法是createWebApplicationContextconfigureAndRefreshWebApplicationContext方法。createWebApplicationContext方法用于返回XmlWebApplicationContext實例,即Web環境下的SpringIoC容器。configureAndRefreshWebApplicationContext用于配XmlWebApplicationContext,讀取web.xml中通過contextConfigLocation標簽指定的XML文件,通過調用refresh來調用AbstractApplicationContext中的refresh初始化。

BeanFactory實例化XML文件中配置的bean,Spring將配置文件的bean的信息解析成為一個個的BeanDefinition對象并裝入到容器的Bean定義注冊表,但此時Bean還未初始化;obtainFreshBeanFactory()會調用自身的refreshBeanFactory(),而refreshBeanFactory()方法由子類AbstractRefreshableApplicationContext實現,該方法返回了一個創建的DefaultListableBeanFactory對象,這個對象就是由ApplicationContext管理的BeanFactory容器對象;

調用工廠后處理器:根據反射機制從BeanDefinitionRegistry中找出所有BeanFactoryPostProcessor類型的Bean,并調用其postProcessBeanFactory()接口方法。經過第一步加載配置文件,已經把配置文件中定義的所有bean裝載到BeanDefinitionRegistry這個Beanfactory中,對于ApplicationContext應用來說這個BeanDefinitionRegistry類型的BeanFactory就是Spring默認的DefaultListableBeanFactory

注冊Bean后處理器:根據反射機制從BeanDefinitionRegistry中找出所有BeanPostProcessor類型的Bean,并將它們注冊到容器Bean后處理器的注冊表中;

初始化消息源:初始化容器的國際化信息資源;

初始化應用上下文事件廣播器;

初始化其他特殊的Bean;

注冊事件監聽器;

初始化singleton的Bean:實例化所有singleton的Bean,并將它們放入Spring容器的緩存中;

發布上下文刷新事件:在此處時容器已經啟動完成,發布容器refresh事件創建上下文刷新事件,事件廣播器負責將些事件廣播到每個注冊的事件監聽器中。

7.3 Bean加載流程

ResourceLoader從存儲介質中加載Spring配置文件,并使用Resource表示這個配置文件的資源;

BeanDefinitionReader讀取Resource所指向的配置文件資源,然后解析配置文件。配置文件中每一個解析成一個BeanDefinition對象,并保存到BeanDefinitionRegistry中;

容器掃描BeanDefinitionRegistry中的BeanDefinition,使用Java的反射機制自動識別出Bean工廠后處理器(實現BeanFactoryPostProcessor接口)的Bean,然后調用這些Bean工廠后處理器對BeanDefinitionRegistry中的BeanDefinition進行加工處理。主要完成以下兩項工作:

對使用到占位符的元素標簽進行解析,得到最終的配置值,這意味對一些半成品式的BeanDefinition對象進行加工處理并得到成品的BeanDefinition對象;

BeanDefinitionRegistry中的BeanDefinition進行掃描,通過Java反射機制找出所有屬性編輯器的Bean(實現java.beans.PropertyEditor接口的Bean),并自動將它們注冊到Spring容器的屬性編輯器注冊表中(PropertyEditorRegistry);

Spring容器從BeanDefinitionRegistry中取出加工后的BeanDefinition,并調用InstantiationStrategy著手進行Bean實例化的工作;

在實例化Bean時,Spring容器使用BeanWrapper對Bean進行封裝,BeanWrapper提供了很多以Java反射機制操作Bean的方法,它將結合該Bean的BeanDefinition以及容器中屬性編輯器,完成Bean屬性的設置工作;

利用容器中注冊的Bean后處理器(實現BeanPostProcessor接口的Bean)對已經完成屬性設置工作的Bean進行后續加工,直接裝配出一個準備就緒的Bean。

8. Spring事件

Spring事件體系包括三個組件:事件,事件監聽器,事件廣播器。

事件:ApplicationEvent

事件監聽器:ApplicationListener,對監聽到的事件進行處理。

事件廣播器:ApplicationEventMulticaster,將Spring publish的事件廣播給所有的監聽器。Spring在ApplicationContext接口的抽象實現類AbstractApplicationContext中完成了事件體系的搭建。

AbstractApplicationContext擁有一個applicationEventMulticaster成員變量,applicationEventMulticaster提供了容器監聽器的注冊表。

8.1 事件廣播器的初始化
private void initApplicationEventMulticaster() throws BeansException {  
    if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME )) {  
        this.applicationEventMulticaster = (ApplicationEventMulticaster)  
            getBean( APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class );  
        if (logger.isInfoEnabled()) {
            logger.info("Using ApplicationEventMulticaster [" + this. applicationEventMulticaster + "]" );
        }  
    }  
    else {  
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();  
        if (logger.isInfoEnabled()) {
            logger.info("Unable to locate ApplicationEventMulticaster with name ""+  APPLICATION_EVENT_MULTICASTER_BEAN_NAME +  
                        "": using default [" + this .applicationEventMulticaster + "]");  
        }  
    }  
 }  

用戶可以在配置文件中為容器定義一個自定義的事件廣播器,只要實現ApplicationEventMulticaster就可以了,Spring會通過反射的機制將其注冊成容器的事件廣播器,如果沒有找到配置的外部事件廣播器,Spring自動使用 SimpleApplicationEventMulticaster作為事件廣播器。

8.2 注冊事件監聽器
private void registerListeners () throws BeansException {
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let post-processors apply to them!
    Collection listeners = getBeansOfType(ApplicationListener.class,true,false).values();
    for (Iterator it = listeners.iterator(); it.hasNext();) {
        addListener((ApplicationListener) it.next());
    }
}
protected void addListener(ApplicationListener listener) {
    getApplicationEventMulticaster().addApplicationListener(listener);
}

Spring根據反射機制,使用ListableBeanFactorygetBeansOfType方法,從BeanDefinitionRegistry中找出所有實現 org.springframework.context.ApplicationListener的Bean,將它們注冊為容器的事件監聽器,實際的操作就是將其添加到事件廣播器所提供的監聽器注冊表中。

8.3 發布事件
public void publishEvent(ApplicationEvent event) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isDebugEnabled()) {
        logger.debug("Publishing event in context ["
                      + getDisplayName() + "]: " + event);
    }
    getApplicationEventMulticaster().multicastEvent(event);
    if (this.parent != null) {
        this.parent.publishEvent(event);
    }
}

AbstractApplicationContextpublishEvent方法中, Spring委托ApplicationEventMulticaster將事件通知給所有的事件監聽器

8.4 Spring默認的事件廣播器SimpleApplicationEventMulticaster
public void multicastEvent( final ApplicationEvent event) {
    for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {
        final ApplicationListener listener = (ApplicationListener) it.next();
        getTaskExecutor().execute(new Runnable() {
            public void run() {
                listener.onApplicationEvent(event);
            }
        });
    }
 }

遍歷注冊的每個監聽器,并啟動來調用每個監聽器的onApplicationEvent方法。
由于SimpleApplicationEventMulticastertaskExecutor的實現類是SyncTaskExecutor,因此,事件監聽器對事件的處理,是同步進行的。

8.5 舉例

springEvent.xml




    

MockEvent

package com.event;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ApplicationContextEvent;

public class MockEvent extends ApplicationContextEvent {

    public MockEvent(ApplicationContext source) {
        super(source);
    }
}

MockEventListener

package com.event;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class MockEventListener implements ApplicationListener {

    public void onApplicationEvent(MockEvent event) {
        System.out.println("mock event received");
    }
}

MockEventPublisher

package com.event;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;;

@Component
public class MockEventPublisher implements ApplicationContextAware {

    private ApplicationContext ctx;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }

    public void publishEvent() {
        System.out.println("publish event");
        MockEvent event = new MockEvent(this.ctx);
        ctx.publishEvent(event);
    }
}

MockEventTest

package com.event;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MockEventTest {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
                "/springEvent.xml");
        MockEventPublisher publisher = ctx.getBean(MockEventPublisher.class);
        publisher.publishEvent();
        ctx.close();
    }
}

結果

二月 09, 2017 9:57:43 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@69d0a921: startup date [Thu Feb 09 21:57:43 CST 2017]; root of context hierarchy
二月 09, 2017 9:57:43 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [springEvent.xml]
publish event
mock event received
二月 09, 2017 9:57:44 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose
信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@69d0a921: startup date [Thu Feb 09 21:57:43 CST 2017]; root of context hierarchy

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66617.html

相關文章

  • java 異步查詢轉同步多種實現方式:循環等待,CountDownLatch,EventListen

    摘要:異步轉同步業務需求有些接口查詢反饋結果是異步返回的,無法立刻獲取查詢結果。正常處理邏輯觸發異步操作,然后傳遞一個唯一標識。等到異步結果返回,根據傳入的唯一標識,匹配此次結果。異步轉同步查詢空循環短暫等待。 異步轉同步 業務需求 有些接口查詢反饋結果是異步返回的,無法立刻獲取查詢結果。 正常處理邏輯 觸發異步操作,然后傳遞一個唯一標識。 等到異步結果返回,根據傳入的唯一標識,匹配此次結果...

    Jochen 評論0 收藏0
  • Spring IOC入門:從Hello world到Spring

    摘要:但還有問題,這個類既控制了參數的輸入,又控制了參數的輸出。換句話說就是消息的輸入和輸出是耦合在一起的。進一步解耦讓我們更進一步。接下來解耦消息的生產方。實際上,到這里已經完成了一個簡易版的實現。 從Hello world開始 先上一段代碼: public class HelloWorldTest { public static void main(String[] args)...

    X1nFLY 評論0 收藏0
  • Spring 的基本應用——IoC 和 AOP

    摘要:的兩大核心機制是控制反轉和面向切面編程,對于初學者來講,搞清楚這兩個核心機制就掌握了的基本應用。配置對象張三添加標簽對應屬性名,是屬性的值。若包含特殊字符,比如張三,使用張三進行配置,如下所示。 前言 對于任何一個 Java 開發人員,Spring 的大名一定如雷貫耳,在行業中可謂是無人不知、無人不曉,說它是 Java 領域第一框架毫不為過。 showImg(https://segme...

    DirtyMind 評論0 收藏0
  • Spring框架學習筆記(一):官方文檔介紹,IoC與AOP概念學習

    摘要:構造函數注入通過調用類的構造函數,將接口實現類通過構造函數變量傳入。而在中,其使用橫切技術,將這類代碼從原屬的封裝對象中提取出來,封裝到一個可重用模塊中,稱為。 最近實習用到Spring的開發框架,但是之前沒有接觸過,因此希望利用網上的資源來學習以下。 Spring官方給出了非常全面的介紹,非常適合我這種完全的小白……在這一系列學習中,我閱讀的主要資源是5.1.2 Reference ...

    mindwind 評論0 收藏0
  • Spring IoC學習總結

    摘要:學習總結學習整理的一些筆記,很簡單。大部分認為和只是不同的叫法而已。依賴注入的兩種方式和注解使用注釋驅動的功能源碼剖析 Spring IoC學習總結 學習spring Ioc整理的一些筆記,很簡單。分享給大家。 IoC 基本概念 在這之前,我們先記住一句話。好萊塢原則:Dont call us, we will call you.其實這句話很恰當地形容了反轉的意味;Ioc, Inve...

    silencezwm 評論0 收藏0

發表評論

0條評論

luzhuqun

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<