Spring5.0源码深度解析之容器的功能扩展

Stella981
• 阅读 269

Spring5.0源码深度解析之容器的功能扩展

版权所有:https://my.oschina.net/u/3995125,禁止转载

容器的功能扩展

前期准备:

同样,我们还是以 AnnotationConfigApplicationContext 作为切入点,开始对整体功能进行分析。

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }

一:创建IOC容器

进入this();

public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); }

先执行父类的初始化方法,创建IOC容器

public GenericApplicationContext() { this.beanFactory = new DefaultListableBeanFactory(); }

Spring5.0源码深度解析之容器的功能扩展

2.进入AnnotatedBeanDefinitionReader方法执行初始化方法创建BeanDefinition读取器

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(environment, "Environment must not be null"); this.registry = registry; this.conditionEvaluator = new ConditionEvaluator(registry, environment, null); AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); }

AnnotationConfigUtils获取所有BeanPostProcessor的Bean,把下面6个对象注入到IOC容器中了

Spring5.0源码深度解析之容器的功能扩展

这里用到了CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 、AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME 等几个常量

常量

对应的BeanPostProcessor

 对应的注解

CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME

ConfigurationClassPostProcessor

@Configuration

AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME

AutowiredAnnotationBeanPostProcessor    

 @AutoWired

REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME

RequiredAnnotationBeanPostProcessor

@Required

COMMON_ANNOTATION_PROCESSOR_BEAN_NAME

CommonAnnotationBeanPostProcessor

@javax.annotation.PostConstruct、@javax.annotation.PreDestroy

等等,还有几个,就不列了。

3.进入ClassPathBeanDefinitionScanner方法创建classPath下扫描器

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry;

if (useDefaultFilters) { registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); }

Spring5.0源码深度解析之容器的功能扩展

二:注册配置类

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }

public void register(Class<?>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); this.reader.register(annotatedClasses); }

public void register(Class... annotatedClasses) { for (Class annotatedClass : annotatedClasses) { registerBean(annotatedClass); } }

Spring5.0源码深度解析之容器的功能扩展

public void registerBean(Class<?> annotatedClass) { doRegisterBean(annotatedClass, null, null, null); }

Spring5.0源码深度解析之容器的功能扩展

void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);//创建BeanDefinition对象 if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {    //处理 @Condition注解 return; }

abd.setInstanceSupplier(instanceSupplier); //设置对象是单例模式还是多例模式,默认单例 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName());    //获取BeanName,设置的化就采用默认值,否则类名第一个字母小写 String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); //处理Lazy,primary等注解  .....

BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);//判断对象是否需要代理,不需要直接返回,需要的化,重新创建BeanDefinition加入代理的信息 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);    //注册配置类到IOC容器 }

Spring5.0源码深度解析之容器的功能扩展

扩展功能

进入 refresh()方法,可以说refresh函数中包括了几乎ApplicationContext中提供的全部功能,而且此函数中逻辑非常清晰明了。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }

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**();**//初始化BeanFacgtory**

  // Prepare the bean factory for use in this context.
  **prepareBeanFactory**(beanFactory);**//初始化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);**//激活各种BeanFactory处理器**

     // Register bean processors that intercept bean creation.
     **registerBeanPostProcessors**(beanFactory);**//注册拦截Bean创建的Bean处理器,这里只是注册,真正的调用是在getBean的时候**

     // Initialize message source for this context.
     **initMessageSource**();**//为上下文初始化Message源,集不同语言的消息体,国际化处理**

     // Initialize event multicaster for this context.
     **initApplicationEventMulticaster**();**//初始化应用消息广播器,并放入applicationEventMulticaster bean中**

     // Initialize other special beans in specific context subclasses.
     **onRefresh**();**//留给子类来初始化其它的Bean**

     // Check for listener beans and register them.
     **registerListeners**();**//在所有注册的Bean中查找Listener bean,注册到消息广播器中**

     // Instantiate all remaining (non-lazy-init) singletons.
     **finishBeanFactoryInitialization**(beanFactory);**//初始化剩下的单实例(非惰性)**

     // Last step: publish corresponding event.
     **finishRefresh**();**//完成刷新过程,通知生命周期处理器 LifecycleProcessor刷新过程,同时发出 ContextRefreshedEvent 通知别人**
  }

  catch (BeansException ex) {
   
     // Destroy already created singletons to avoid dangling resources.
     **destroyBeans**();**//销毁Bean**

     // Reset 'active' flag.
     **cancelRefresh**(ex);**//更改活跃状态**

     // Propagate exception to caller.
     throw ex;
  }

} }

准备刷新上下文环境

prepareRefresh();函数主要作用是对系统属性及环境变量的初始化及验证

/** * Prepare this context for refreshing, setting its startup date and * active flag as well as performing any initialization of property sources. */ protected void prepareRefresh() { this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true);

if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); }

// Initialize any placeholder property sources in the context environment initPropertySources();//留给子类覆盖

// Validate that all properties marked as required are resolvable // see ConfigurablePropertyResolver#setRequiredProperties getEnvironment().validateRequiredProperties();//验证需要的属性文件是否都已经放入环境中去了

// Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... this.earlyApplicationEvents = new LinkedHashSet<>(); }

initPropertySources是空的,没有任何逻辑处理, 而getEnvironment().validateRequiredProperties()也是因为没有需要验证的属性而没有做任何处理,然而这两个方法作用还是很大的。那么该怎么用呢?

1.initPropertySources正符合Spring的开放式结构设计,给用户最大的扩展Spring的能力。

2.validateRequiredProperties则是对属性进行验证,那么如何验证呢?我们举个例子来说明下:

public class MyAnnotationConfigApplication extends AnnotationConfigApplicationContext { public MyAnnotationConfigApplication(Class<?>... annotatedClasses){ super(annotatedClasses); } @Override protected void initPropertySources(){ //添加验证要求 getEnvironment().setRequiredProperties("VAR"); } }

我们自定义了继承自AnnotationConfigApplicationContext的MyAnnotationConfigApplication,并重写了initPropertySources方法,在方法中添加了我们的个性化需求,那么在验证的时候也就是程序走到

validateRequiredProperties()代码的时候,我们还需要替换掉原有的AnnotationConfigApplicationContext为我们自定义的****MyAnnotationConfigApplication。

public class Test002 { public static void main(String[] args) { ApplicationContext context = new MyAnnotationConfigApplication(MyConfig.class); Object payEntity = context.getBean("payEntity"); System.out.println(payEntity); } }

如果系统并没有检测到对应的VAR环境变量,那么就会抛出异常:

Spring5.0源码深度解析之容器的功能扩展

初始化BeanFacgtory

obtainFreshBeanFactory()方法的作用是:经过这个方法,ApplicationContext就已经拥有了BeanFactory的全部功能。

/** * Tell the subclass to refresh the internal bean factory. * @return the fresh BeanFactory instance * @see #refreshBeanFactory() * @see #getBeanFactory() */ protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {     //初始化BeanFactory refreshBeanFactory();     //返回当前实体的BeanFactory属性 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }

方法中将核心实现委托给了refreshBeanFactory:

/** * This implementation performs an actual refresh of this context's underlying * bean factory, shutting down the previous bean factory (if any) and * initializing a fresh bean factory for the next phase of the context's lifecycle. */ @Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { DefaultListableBeanFactory beanFactory = createBeanFactory();//创建DefaultListableBeanFactory beanFactory.setSerializationId(getId());//序列化id customizeBeanFactory(beanFactory);//定制BeanFactory,设置相关属性,是否允许循环依赖,是否允许覆盖 loadBeanDefinitions(beanFactory);//加载BeanDefinition synchronized (this.beanFactoryMonitor) { ** this.beanFactory = beanFactory**; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

1.定制BeanFactory

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {     //如果属性不为空,则设置给beanFactory对象相应属性,此属性的含义是:是否允许覆盖同名称的不同定义的对象 if (this.allowBeanDefinitionOverriding != null) { beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); }     //如果属性不为空,设置给beanFactory对象相应的属性,这块属性的含义是:是否允许Bean之间存在循环依赖 if (this.allowCircularReferences != null) { beanFactory.setAllowCircularReferences(this.allowCircularReferences); } }

对于允许覆盖和允许循环依赖的设置这里只是进行了非空判断,如果不为空的化要进行设置,但是这里没有设置,所以还是那个套路,使用子类覆盖方法。

public class MyAnnotationConfigApplication extends AnnotationConfigApplicationContext { public MyAnnotationConfigApplication(Class<?>... annotatedClasses){ super(annotatedClasses); } protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory){ super.setAllowBeanDefinitionOverriding(false);//是否允许覆盖同名称的不同定义的对象 super.setAllowCircularReferences(false);//是否允许Bean之间存在循环依赖 } }

2.加载BeanDefinition

/** * Loads the bean definitions via an XmlBeanDefinitionReader. * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader * @see #initBeanDefinitionReader * @see #loadBeanDefinitions */ @Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { // Create a new XmlBeanDefinitionReader for the given BeanFactory. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//为指定的beanFactory创建XmlBeanDefinitionReader

// Configure the bean definition reader with this context's // resource loading environment. beanDefinitionReader.setEnvironment(this.getEnvironment());//对beanDefinitionReader进行环境变量的设置 beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

// Allow a subclass to provide custom initialization of the reader, // then proceed with actually loading the bean definitions. initBeanDefinitionReader(beanDefinitionReader);//进行设置可以覆盖 loadBeanDefinitions(beanDefinitionReader); }

在初始化了DefaultListableBeanFactoryXmlBeanDefinitionReader后就可以进行配置文件的读取了

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException { Assert.notNull(resources, "Resource array must not be null"); int counter = 0; for (Resource resource : resources) { counter += loadBeanDefinitions(resource); } return counter; }

经过此步骤,类型DefaultListableBeanFactory的变量beanFactory已经包含了所有已经解析好的配置

功能扩展

进入函数prepareBeanFactory前,Spring已经完成了对配置的解析,而ApplicationContext在功能上的扩展也由此展开。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // Tell the internal bean factory to use the context's class loader etc. beanFactory.setBeanClassLoader(getClassLoader());//设置BeanFactory的classLoader为当前context的classLoader beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));//设置beanFactory的表达式语言处理器,默认可以使用#{bean.xx}的形式来调用相关的属性值。 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));//为BeanFactory增加了一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具

// Configure the bean factory with context callbacks. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));**//添加BeanPostProcessor

    //设置了几个忽略自定装配的接口** 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);

// Register early post-processor for detecting inner beans as ApplicationListeners. beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// 增加了对AspectJ的支持 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }

// 添加了默认的系统环境bean if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }

上面函数中主要进行了几个方面的扩展

  • 增加了对SpEL语言的支持
  • 增加对属性编辑器的支持
  • 增加了对一些内置类,比如实现了Aware接口的类信息注入
  • 设置了依赖功能可忽略接口
  • 注册一些固定依赖的属性
  • 增加了AspectJ的支持,后面再去分析
  • 将相关环境变量及属性注册以单例模式注册

上面可扩展功能很多,我就不一一介绍了,下面我们来挑几个我们感兴趣的函数来分析下:

beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)),其主要目的就是注册个BeanPostProcessor,而真正的逻辑还是在ApplicationContextAwareProcessor中

Spring5.0源码深度解析之容器的功能扩展

ApplicationContextAwareProcessor实现了BeanPostProcessor接口,我们回顾下之前讲解的内容,在Bean实例化的时候,也就是Spring激活Bean的init-method方法前后,

会调用BeanPostProcessor的postProcessBeforeInitializationpostProcessAfterInitialization方法。所以我们也就去看看ApplicationContextAwareProcessor对这两个方法的实现。

@Override public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; }

对于后置处理器BeanPostProcessor的后置处理方法中并没有做任何逻辑处理,那么我们转向后置处理器的前置处理

public Object postProcessBeforeInitialization(final 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((PrivilegedAction) () -> { invokeAwareInterfaces(bean); return null; }, acc); } else { 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); } } }

postProcessBeforeInitialization方法中调用了invokeAwareInterfaces。从invokeAwareInterfaces方法中,我们或许已经差不多知道了Spring的用意,实现了这些Aware接口的Bean在被初始化后,可以取到一些对于的资源。

示例:

@Component public class MyApplicationContext implements ApplicationContextAware { /** * spring底层中为什么能够实现ApplicationContextAware接口 就能够拿到ApplicationContext * @param applicationContext * @throws BeansException */ @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("applicationContext:>>>>"+applicationContext); } }

Spring5.0源码深度解析之容器的功能扩展

BeanFactory的后处理

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }

注册BeanPostProcessor

我们自定义MyInstantiationAwareBeanPostProcessor实现BeanPostProcessor 接口

@Component public class MyInstantiationAwareBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("postProcessBeforeInitialization...."); return null; }

@Override
public Object **postProcessAfterInitialization**(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessAfterInitialization....");
    return null;
}

}

@Import(MyInstantiationAwareBeanPostProcessor.class)

结果输出:每次初始化一个Bean就会在之前和之后处理一些自定义逻辑

postProcessBeforeInitialization....
4.bean init方法执行..
postProcessAfterInitialization....

初始化ApplicationEventMulticaster

/** * Initialize the ApplicationEventMulticaster. * Uses SimpleApplicationEventMulticaster if none defined in the context. * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }

进入SimpleApplicationEventMulticaster找到这段代码:

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { doInvokeListener(listener, event); } }

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {         .... listener.onApplicationEvent(event); }

Spring5.0源码深度解析之容器的功能扩展

可以推断,当产生Spring事件的时候会默认使用SimpleApplicationEventMulticastermulticastEvent来广播事件遍历所有监听器,并使用监听器中的onApplicationEvent方法来进行监听事件的处理。

而对于每个监听器来说其实都可以获取到产生的事件,但是是否进行处理则由事件监听器来决定。

注册监听器

进入registerListeners函数,开始注册监听器:

protected void registerListeners() {

for (ApplicationListener<?> listener : getApplicationListeners()) {//硬编码方式注册的监听器处理 getApplicationEventMulticaster().addApplicationListener(listener); }

String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);//配置文件注册的监听器处理 for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } Set earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }

Application下抽象子类ApplicationContextEvent的下面有4个已经实现好的事件 

  • ContextClosedEvent(容器关闭时)
  • ContextRefreshedEvent(容器刷新时)
  • ContextStartedEvent(容器启动时候)
  • ContextStoppedEvent(容器停止的时候)

同样,这四个事件都继承了ApplicationEvent,如果我们想自定义事件,也可以通过继承ApplicationEvent来实现 

使用示例:

1.定义监听事件

public class TestEvent extends ApplicationEvent { private String msg; public TestEvent(Object source){ super(source); } public TestEvent(Object source,String msg){ super(source); this.msg=msg; } public void print(){ System.out.println(msg); } }

2.定义监听器

public class TestListener implements ApplicationListener { @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof TestEvent){ TestEvent testEvent= (TestEvent)event; testEvent.print(); } } }

注入容器

@Import(TestListener.class)

测试:

public class Test001 {

public static void main(String\[\] args) {
    /\*\*
     \* IOC容器初始化单例对象都是循环遍历调用getBean方法
     \*/
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
    TestEvent testEvent = new TestEvent("hello", "hello word");
    applicationContext.publishEvent(testEvent);
}

}

输出结果:

Spring5.0源码深度解析之容器的功能扩展

我们在补充一个注解形式的例子:

public class TestEvent extends ApplicationEvent {

private String msg;
public TestEvent(Object source){
    super(source);
}
public TestEvent(Object source,String msg){
    super(source);
    this.msg=msg;
}
public void print(){
    System.out.println("注册监听器..,TestEvent....");
}

}

@Component public class MyAnnotationListener {

@EventListener public String listener1(TestEvent event) { if (event instanceof TestEvent){ TestEvent testEvent=event; testEvent.print(); } return "xd"; } }

@Import(MyAnnotationListener.class)

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class); MyAnnotationListener myAnnotationListener = new MyAnnotationListener(); applicationContext.publishEvent(myAnnotationListener.listener1(new TestEvent("jj")));

输出:

Spring5.0源码深度解析之容器的功能扩展

初始化非延迟加载单例

进入finishBeanFactoryInitialization函数初始化所有非懒加载Bean

/** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */ protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {

if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService(//定义转换器从String转为Date的方式,可以自己扩展,我就不多说了 beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } beanFactory.setTempClassLoader(null);

// Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration();//冻结所有Bean的定义,说明注册的Bean定义将不被修改或处理。

// Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons();//初始化剩下的单实例(非惰性) }

冻结配置

@Override public void freezeConfiguration() { this.configurationFrozen = true; this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);

初始化非延迟加载

ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化。提前实例化的好处是,在配置中任何错误就会立即被发现Z(否则的化,一旦出错,排除bug相当困难)。

public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); }

// Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List beanNames = new ArrayList<>(this.beanDefinitionNames);

// Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName); boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction) () -> ((SmartFactoryBean) factory).isEagerInit(), getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } else { getBean(beanName); } } }

finishRefresh

在Spring中还提供了Lifecycle接口,Lifecycle接口中包含start/stop方法,实现此接口后Spring会保证在启动的时候调用其start方法开始生命周期,并且在spring关闭的时候调用stop方法来结束生命周期,

通常用来配置后台程序,在启动后一直运行(such as MQ进行轮询等)。

/** * Finish the refresh of this context, invoking the LifecycleProcessor's * onRefresh() method and publishing the * {@link org.springframework.context.event.ContextRefreshedEvent}. */ protected void finishRefresh() { // Clear context-level resource caches (such as ASM metadata from scanning). clearResourceCaches();

// Initialize lifecycle processor for this context. initLifecycleProcessor();//当ApplicationContext启动或者停止时,会通过LifecycleProcessor来与所有声明的bean的周期做状态更新,而在LifecycleProcessor使用前需要初始化

// Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh();//启动所有实现了Lifecycle接口的bean

// Publish the final event. publishEvent(new ContextRefreshedEvent(this));//当完成ApplicationContext初始化的时候,要通过Spring中的事件发布机制来发出ContextRefreshedEvent监听事件,以保证对应的监听器可以做进一步的逻辑处理

// Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }

到这里,我们就谈完了!!!

参考书籍:Spring源码深度解析

版权所有:https://my.oschina.net/u/3995125,禁止转载

点赞
收藏
评论区
推荐文章
浅梦一笑 浅梦一笑
2个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
技术小男生 技术小男生
2个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi /etc/profile2:按字母键i进入编辑模式,在最底部添加内容: JAVAHOME/opt/jdk1.8.0152 CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jar PATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
2个月前
Java面向对象试题
1、 请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。 创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现 接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿 吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
2个月前
css问题
1、 在IOS中图片不显示(给图片加了圆角或者img没有父级) <div<img src""/</div div {width: 20px; height: 20px; borderradius: 20px; overflow: h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录 问题 用navicat导入数据时,报错: 原因这是因为当前的MySQL不支持datetime为0的情况。 解决修改sql\mode: sql\mode:SQL Mode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。 全局s
小森森 小森森
2个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本 欢迎添加左边的微信一起探讨!项目地址:](https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n) \2. Bug修复更新日历 2. 情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意), \ \ 和 注意
晴空闲云 晴空闲云
2个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。 盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
1个月前
快速入门|使用MemFire Cloud构建React Native应用程序
> MemFire Cloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Stella981 Stella981
1年前
Spring5.0源码深度解析之SpringBean声明事务底层实现原理
![](https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=0c730b84bd19ebc4c078719fba1da8c1/37d12f2eb9389b503a80d4b38b35e5dde6116ed7.jpg) ================
Easter79 Easter79
1年前
springboot源码分析
![](https://gss1.bdstatic.com/-vo3dSag_xI4khGkpoWK1HF6hhy/baike/w%3D268%3Bg%3D0/sign=0c730b84bd19ebc4c078719fba1da8c1/37d12f2eb9389b503a80d4b38b35e5dde6116ed7.jpg) ================
helloworld_28799839 helloworld_28799839
2个月前
常用知识整理
# Javascript ## 判断对象是否为空 ```js Object.keys(myObject).length === 0 ``` ## 经常使用的三元运算 > 我们经常遇到处理表格列状态字段如 `status` 的时候可以用到 ``` vue