成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Learn Spring - Spring IoC

luzhuqun / 1368人閱讀

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

1. Spring的資源抽象接口

假如有一個(gè)文件位于Web應(yīng)用的類路徑下,用戶可以通過以下方式對這個(gè)文件資源進(jìn)行訪問:

通過FileSystemResource以文件系統(tǒng)絕對路徑的方式進(jìn)行訪問;

通過ClassPathResource以類路徑的方式進(jìn)行訪問;

通過ServletContextResource以相對于Web應(yīng)用根目錄的方式進(jìn)行訪問。

2. BeanFactory的類體系結(jié)構(gòu)

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

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

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

ConfigurableBeanFactory:增強(qiáng)了IoC容器的可定制性

AutowireCapableBeanFactory:定義了將容器中的bean按照某種規(guī)則進(jìn)行自動(dòng)裝配的方法

SingletonBeanRegistry:定義了允許在運(yùn)行期向容器注冊單實(shí)例bean的方法

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

Spring在DefaultSingletonBeanRegistry類中提供了一個(gè)用于緩存單實(shí)例bean的緩存器,以HashMap實(shí)現(xiàn),單實(shí)例的bean以beanName為key保存在這個(gè)HashMap

3. ApplicationContext的類體系結(jié)構(gòu)

ApplicationEventPublisher:讓容器擁有發(fā)布應(yīng)用上下文事件的功能,包括容器啟動(dòng)事件、關(guān)閉事件等。實(shí)現(xiàn)了ApplicationListener事件監(jiān)聽接口的Bean 可以接收到容器事件,并對事件進(jìn)行響應(yīng)處理。在ApplicationContext抽象實(shí)現(xiàn)類AbstractApplicationContext中,我們可以發(fā)現(xiàn)存在一個(gè)ApplicationEventMulticaster,它負(fù)責(zé)保存所有監(jiān)聽器,以便在容器產(chǎn)生上下文事件時(shí)通知這些事件監(jiān)聽者。

MessageSource:為應(yīng)用提供i18n國際化消息訪問的功能;

ResourcePatternResolver:所有ApplicationContext實(shí)現(xiàn)類都實(shí)現(xiàn)了類似于PathMatchingResourcePatternResolver的功能,可以通過帶前綴的Ant風(fēng)格的資源文件路徑裝載Spring的配置文件。

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

ConfigurableApplicationContext擴(kuò)展于ApplicationContext,它新增加了兩個(gè)主要的方法:refresh()close(),讓ApplicationContext具有啟動(dòng)、刷新和關(guān)閉應(yīng)用上下文的能力。在應(yīng)用上下文關(guān)閉的情況下調(diào)用refresh()即可啟動(dòng)應(yīng)用上下文,在已經(jīng)啟動(dòng)的狀態(tài)下,調(diào)用refresh()則清除緩存并重新裝載配置信息,而調(diào)用close()則可關(guān)閉應(yīng)用上下文。

4. WebApplicantContext體系結(jié)構(gòu)

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

WebApplicationContext擴(kuò)展了ApplicationContext,WebApplicationContext定義了一個(gè)常量ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在上下文啟動(dòng)時(shí),我們可以直接通過下面的語句從web容器中獲取WebApplicationContext:

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

如果容器注冊InstantiationAwareBeanPostProcessor接口,調(diào)用postProcessBeforeInstantiation方法

Bean的實(shí)例化(調(diào)用默認(rèn)構(gòu)造器)

如果容器注冊InstantiationAwareBeanPostProcessor接口,調(diào)用postProcessAfterInstantiation方法

如果容器注冊InstantiationAwareBeanPostProcessor接口,調(diào)用postProcessPropertyValues方法

根據(jù)配置設(shè)置屬性值

如果Bean實(shí)現(xiàn)了BeanNameAware接口,調(diào)用BeanNameAware接口的setBeanName方法

如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,調(diào)用BeanFactoryAware接口的setBeanFactory方法

如果容器注冊了BeanPostProcessor接口,調(diào)用BeanPostProcessor接口的postProcessBeforeInitialization方法

如果Bean實(shí)現(xiàn)了InitializingBean接口,調(diào)用InitializingBean接口的afterPropertiesSet方法

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

如果容器注冊了BeanPostProcessor接口,調(diào)用BeanPostProcessor接口的postProcessAfterInitialization方法

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

如果是多例模式,將Bean交給調(diào)用者。

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

bean自身的方法:如調(diào)用bean構(gòu)造函數(shù)實(shí)例化bean,調(diào)用Setter設(shè)置bean的屬性值,以及通過init-methoddestory-method所指定的方法;

bean級生命周期接口方法:如BeanNameAwareBeanFactoryAwareInitializingBeanDisposableBean,這些接口方法由bean類直接實(shí)現(xiàn);

容器級生命周期接口方法:如InstantiationAwareBeanPostProcessorBeanPostProcessor這兩個(gè)接口實(shí)現(xiàn),一般稱它們的實(shí)現(xiàn)類為“后處理器”。

5.3 說明

Spring的AOP等功能即通過BeanPostProcessor實(shí)現(xiàn)

如果通過init-method屬性定義了初始化方法,將執(zhí)行這個(gè)方法

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

對于單例的bean,當(dāng)容器關(guān)閉時(shí),將觸發(fā)Spring對bean的后續(xù)生命周期的管理工作。如果bean實(shí)現(xiàn)了DisposableBean接口,則將調(diào)用接口的destroy()方法

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

后處理器的實(shí)際調(diào)用順序和注冊順序無關(guān),在具有多個(gè)后處理器的情況下,必須通過實(shí)現(xiàn)org.springframework.core.Ordered接口確定調(diào)用順序

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

結(jié)果

二月 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實(shí)現(xiàn)了org.springframework.context.ApplicationContextAware接口,會(huì)增加一個(gè)調(diào)用該接口方法setApplicationContext()的步驟

如果配置文件中聲明了工廠后處理器接口BeanFactoryPostProcessor的實(shí)現(xiàn)類,則應(yīng)用上下文在加載配置文件之后、初始化bean實(shí)例之前將調(diào)用這些BeanFactoryPostProcessor對配置信息進(jìn)行加工處理

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

對bean的初始化,BeanFactory發(fā)生在第一次調(diào)用bean時(shí),而ApplicationContext發(fā)生在初始化容器時(shí)

6.3 測試

MyBeanPostProcessor同上

Car增加對ApplicationContextAware接口的實(shí)現(xiàn),并添加@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();
    }
}

結(jié)果

二月 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. 容器內(nèi)部工作機(jī)制 7.1 啟動(dòng)源碼

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

@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 容器啟動(dòng)流程

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

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

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

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

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

初始化應(yīng)用上下文事件廣播器;

初始化其他特殊的Bean;

注冊事件監(jiān)聽器;

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

發(fā)布上下文刷新事件:在此處時(shí)容器已經(jīng)啟動(dòng)完成,發(fā)布容器refresh事件創(chuàng)建上下文刷新事件,事件廣播器負(fù)責(zé)將些事件廣播到每個(gè)注冊的事件監(jiān)聽器中。

7.3 Bean加載流程

ResourceLoader從存儲(chǔ)介質(zhì)中加載Spring配置文件,并使用Resource表示這個(gè)配置文件的資源;

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

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

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

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

Spring容器從BeanDefinitionRegistry中取出加工后的BeanDefinition,并調(diào)用InstantiationStrategy著手進(jìn)行Bean實(shí)例化的工作;

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

利用容器中注冊的Bean后處理器(實(shí)現(xiàn)BeanPostProcessor接口的Bean)對已經(jīng)完成屬性設(shè)置工作的Bean進(jìn)行后續(xù)加工,直接裝配出一個(gè)準(zhǔn)備就緒的Bean。

8. Spring事件

Spring事件體系包括三個(gè)組件:事件,事件監(jiān)聽器,事件廣播器。

事件:ApplicationEvent

事件監(jiān)聽器:ApplicationListener,對監(jiān)聽到的事件進(jìn)行處理。

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

AbstractApplicationContext擁有一個(gè)applicationEventMulticaster成員變量,applicationEventMulticaster提供了容器監(jiān)聽器的注冊表。

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 + "]");  
        }  
    }  
 }  

用戶可以在配置文件中為容器定義一個(gè)自定義的事件廣播器,只要實(shí)現(xiàn)ApplicationEventMulticaster就可以了,Spring會(huì)通過反射的機(jī)制將其注冊成容器的事件廣播器,如果沒有找到配置的外部事件廣播器,Spring自動(dòng)使用 SimpleApplicationEventMulticaster作為事件廣播器。

8.2 注冊事件監(jiān)聽器
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根據(jù)反射機(jī)制,使用ListableBeanFactorygetBeansOfType方法,從BeanDefinitionRegistry中找出所有實(shí)現(xiàn) org.springframework.context.ApplicationListener的Bean,將它們注冊為容器的事件監(jiān)聽器,實(shí)際的操作就是將其添加到事件廣播器所提供的監(jiān)聽器注冊表中。

8.3 發(fā)布事件
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將事件通知給所有的事件監(jiān)聽器

8.4 Spring默認(rèn)的事件廣播器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);
            }
        });
    }
 }

遍歷注冊的每個(gè)監(jiān)聽器,并啟動(dòng)來調(diào)用每個(gè)監(jiān)聽器的onApplicationEvent方法。
由于SimpleApplicationEventMulticastertaskExecutor的實(shí)現(xiàn)類是SyncTaskExecutor,因此,事件監(jiān)聽器對事件的處理,是同步進(jìn)行的。

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

結(jié)果

二月 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

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66617.html

相關(guān)文章

  • java 異步查詢轉(zhuǎn)同步多種實(shí)現(xiàn)方式:循環(huán)等待,CountDownLatch,EventListen

    摘要:異步轉(zhuǎn)同步業(yè)務(wù)需求有些接口查詢反饋結(jié)果是異步返回的,無法立刻獲取查詢結(jié)果。正常處理邏輯觸發(fā)異步操作,然后傳遞一個(gè)唯一標(biāo)識(shí)。等到異步結(jié)果返回,根據(jù)傳入的唯一標(biāo)識(shí),匹配此次結(jié)果。異步轉(zhuǎn)同步查詢空循環(huán)短暫等待。 異步轉(zhuǎn)同步 業(yè)務(wù)需求 有些接口查詢反饋結(jié)果是異步返回的,無法立刻獲取查詢結(jié)果。 正常處理邏輯 觸發(fā)異步操作,然后傳遞一個(gè)唯一標(biāo)識(shí)。 等到異步結(jié)果返回,根據(jù)傳入的唯一標(biāo)識(shí),匹配此次結(jié)果...

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

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

    X1nFLY 評論0 收藏0
  • Spring 的基本應(yīng)用——IoC 和 AOP

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

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

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

    mindwind 評論0 收藏0
  • Spring IoC學(xué)習(xí)總結(jié)

    摘要:學(xué)習(xí)總結(jié)學(xué)習(xí)整理的一些筆記,很簡單。大部分認(rèn)為和只是不同的叫法而已。依賴注入的兩種方式和注解使用注釋驅(qū)動(dòng)的功能源碼剖析 Spring IoC學(xué)習(xí)總結(jié) 學(xué)習(xí)spring Ioc整理的一些筆記,很簡單。分享給大家。 IoC 基本概念 在這之前,我們先記住一句話。好萊塢原則:Dont call us, we will call you.其實(shí)這句話很恰當(dāng)?shù)匦稳萘朔崔D(zhuǎn)的意味;Ioc, Inve...

    silencezwm 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<