principle
dubbo achieve xml parsing according to schma spring 2.0 and initialize the relevant bean initialization dubbo: service to achieve ServiceBean instance of the corresponding callback service release lifecycle by spring
ServiceBean source
import com.alibaba.dubbo.config.*; import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactoryUtils; 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; importorg.springframework.context.ApplicationListener; Import org.springframework.context.event.ContextRefreshedEvent; Import org.springframework.context.support.AbstractApplicationContext; Import the java.lang.reflect.Method; Import of java.util.ArrayList; Import Classes in java.util .iterator; Import java.util.List; Import a java.util.Map; / ** * the InitializingBean * 1. initialization of calls afterPropertiesSet method * 2 method-higher priority than the init * 3. If the abnormal afterPropertiesSet not-Method, call the init * DisposableBean * 1. when you call context.close time will perform the destroy * ApplicationContextAware * 1. initialize the object will be passed in spring context container * ApplicationListener event * 1.ContextRefreshedEvent when * ApplicationContext is initialized or refreshed, the event is published. This can also occur with refresh () method in ConfigurableApplicationContext interface. * Initialize herein means: Bean all been successfully loaded, and is detected after treatment Bean activated, all the Singleton Bean are pre-instantiated, the container is ready for use the ApplicationContext * 2.ContextStartedEvent * When ConfigurableApplicationContext (ApplicationContext sub-interface) when the start () method to start ApplicationContext, the event is published. * You can survey your database, you can restart or stop any applications received after this event * 3.ContextStoppedEvent * When using ConfigurableApplicationContext interface stop () stop ApplicationContext, published this event. You can do the necessary clean-up work after receiving this event * 5.RequestHandledEvent * 4.ContextClosedEvent * When using ConfigurableApplicationContext interface close () method to close ApplicationContext, the event is published. A closed context to reach the end of the life cycle; it can not be refreshed or restarted * This is a web-specific event telling all bean HTTP request has been serviced. DispatcherServlet can only be applied using a Web application. * When used as a front end of the MVC controller Spring, Spring when the end user requests, the system will automatically trigger the event * @param <T> * / class ServiceBean <T> the extends the ServiceConfig <T> the implements the InitializingBean, The DisposableBean, the ApplicationContextAware , the ApplicationListener <ContextRefreshedEvent> , BeanNameAware { / ** * the ApplicationContextAware interface method * @param applicationContext * / public void setApplicationContext (the applicationContext applicationContext) { the this .applicationContext = applicationContext; SpringExtensionFactory.addApplicationContext(applicationContext); if (applicationContext != null) { SPRING_CONTEXT = applicationContext; try { Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class); method.invoke(applicationContext, this); this.supportedApplicationListener = true; } catch (Throwable var5) { if (applicationContext instanceof AbstractApplicationContext) { try { Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class); if (!method.isAccessible()) { method.setAccessible(true); } method.invoke(applicationContext, this); this.supportedApplicationListener = true; } The catch (Throwable var4) { ; } } } } } / ** * BeanNameAware interface method * @param name * / public void setBeanName (String name) { the this .beanName = name; } / ** * the ApplicationListener implemented method * ContextRefreshedEvent bean is being loaded calls * @param Event * / public void onApplicationEvent (ContextRefreshedEvent Event) { IF ( the this .isDelay () &&!this.isExported() && !this.isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + this.getInterface()); } this.export(); } } /** * InitializingBean * 实现方法 * @throws Exception */ public void afterPropertiesSet() throws Exception { Map providerConfigMap; /** * step1 * dubbo:servie未指定provider * <Dubbo: Provider ID = "test1" = Delay "-. 1" retries = "0" /> * <Dubbo: =-Service Provider "test1" interface = "com.biz.soa.service.seckill.frontend.SoaSeckillFrontService" = REF "soaSeckillFrontServiceImpl" /> * / IF ( the this .getProvider () == null ) { / ** * Step2 * BeanFactoryUtils.beansOfTypeIncludingAncestors to obtain the specified key type and a set of classes and subclasses to achieve as name * / providerConfigMap = the this == .applicationContext null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors ( the this .applicationContext, ProviderConfig.class , to false , to false ); / ** * This is confusing code logic inside the main branch to see below it * / IF (! providerConfigMap = null && providerConfigMap.size ()> 0 ) { the Map <String, ProtocolConfig> = protocolConfigMap the this == .applicationContext null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors ( the this .applicationContext, ProtocolConfig. class , false , false ); Iterator i $; ProviderConfig config; / ** */ if ((protocolConfigMap == null || protocolConfigMap.size() == 0) && protocolConfigMap.size() > 1) { List<ProviderConfig> providerConfigs = new ArrayList(); i$ = protocolConfigMap.values().iterator(); while(i$.hasNext()) { config = (ProviderConfig)i$.next(); if (config.isDefault() != null && config.isDefault()) { providerConfigs.add(config); } } if(! ProviderConfigs.isEmpty ()) { the this .setProviders (providerConfigs); } } the else { ProviderConfig ProviderConfig = null ; I $ = protocolConfigMap.values () Iterator ();. Label318: / ** * Step4 * Note that there default is true either into a first non-default or no default value is set to false will be reported Provider configs Duplicate * <Dubbo: Provider ID = "test1" = Delay "-. 1" retries = "0" /> * <Dubbo: Provider ID = "test2" default = "true" = Delay "-. 1" retries = "0 "/> * / the while ( to true) { Do { IF (! ) {$ I .hasNext () IF (ProviderConfig =! Null ) { the this .setProvider (ProviderConfig); } BREAK label318; } config = (ProviderConfig) .next I $ (); // above default null data plane loop ends column whlie (true) second incoming packets will not empty providerConfig duplicate exception } the while (config.isDefault ()! = null &&! config.isDefault ()); IF ! (ProviderConfig = null ) { the throw new new IllegalStateException ( "Duplicate Provider configs:" ProviderConfig + + "and" + config); } ProviderConfig = config; } } } } the Iterator I $; / ** * as with the above application logic just read tag * <dubbo:application name="soa-promotion-provider"/> */ if (this.getApplication() == null && (this.getProvider() == null || this.getProvider().getApplication() == null)) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ApplicationConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { ApplicationConfig applicationConfig = null; i$ = protocolConfigMap.values().iterator(); label291: while(true) { ApplicationConfig config; do { if (!i$.hasNext()) { if (applicationConfig != null) { this.setApplication(applicationConfig); } break label291; } config = (ApplicationConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); if (applicationConfig != null) { throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } applicationConfig = config; } } } /** * 跟上面一样 读取moudule标签 * <dubbo:module name="soa-promotion-provider" version="1.0" owner="liqianng" organization="信息部"></dubbo:module> */ if (this.getModule() == null && (this.getProvider() == null || this.getProvider().getModule() == null)) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ModuleConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { ModuleConfig moduleConfig = null; i$ = protocolConfigMap.values().iterator(); label270: while(true) { ModuleConfig config; do { if (!i$.hasNext()) { if (moduleConfig != null) { this.setModule(moduleConfig); } break label270; } config = (ModuleConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); if (moduleConfig != null) { throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } moduleConfig = config; } } } ArrayList protocolConfigs; /** * 同上 * <dubbo:registry address="${zookeeper.url}" file=".dubbo/promotion-provider.cache" check="false" /> */ if ((this.getRegistries() == null || this.getRegistries().isEmpty()) && (this.getProvider() == null || this.getProvider().getRegistries() == null || this.getProvider().getRegistries().isEmpty()) && (this.getApplication() == null || this.getApplication().getRegistries() == null || this.getApplication().getRegistries().isEmpty())) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, RegistryConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { protocolConfigs = new ArrayList(); i$ = protocolConfigMap.values().iterator(); label240: while(true) { RegistryConfig config; do { if (!i$.hasNext()) { if (protocolConfigs != null && !protocolConfigs.isEmpty()) { super.setRegistries(protocolConfigs); } break label240; } config = (RegistryConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); protocolConfigs.add(config); } } } /** * //表示从注册中心发现监控地址 * <dubbo:monitor protocol="registry"></dubbo:monitor> */ if (this.getMonitor() == null && (this.getProvider() == null || this.getProvider().getMonitor() == null) && (this.getApplication() == null || this.getApplication().getMonitor() == null)) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, MonitorConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { MonitorConfig monitorConfig = null; i$ = protocolConfigMap.values().iterator(); label215: while(true) { MonitorConfig config; do { if (!i$.hasNext()) { if (monitorConfig != null) { this.setMonitor(monitorConfig); } break label215; } config = (MonitorConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); if (monitorConfig != null) { throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } } /** * 获取配置的协议信息 * <dubbo:protocol register="false" name="dubbo" port="23888" threadpool="fixed" threads="500" dispatcher="message"/> * */ if ((this.getProtocols() == null || this.getProtocols().isEmpty()) && (this.getProvider() == null || this.getProvider().getProtocols() == null || this.getProvider().getProtocols().isEmpty())) { protocolConfigMap = this.applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(this.applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { protocolConfigs = new ArrayList(); i$ = protocolConfigMap.values().iterator(); label190: while(true) { ProtocolConfig config; do { if (!i$.hasNext()) { if (protocolConfigs != null && !protocolConfigs.isEmpty()) { super.setProtocols(protocolConfigs); } break label190; } config = (ProtocolConfig)i$.next(); } while(config.isDefault() != null && !config.isDefault()); protocolConfigs.add(config); } } } if ((this.getPath() == null || this.getPath().length() == 0) && this.beanName != null && this.beanName.length() > 0 && this.getInterface() != null && this.getInterface().length() > 0 && this.beanName.startsWith(this.getInterface())) { the this .setPath ( the this .beanName); } / ** * whether a default registration service delay in milliseconds to 0 * / IF (! the this {.isDelay ()) the this.export(); } } / ** * whether to delay loading * @return * / Private Boolean isDelay () { // Get the current service tag Integer Delay = the this .getDelay (); ProviderConfig Provider = the this .getProvider (); // if no obtaining from the provider tag IF (Delay == null && provider =! null ) { Delay = provider.getDelay (); } return the this .supportedApplicationListener && (Delay == null || Delay == -1); } /** * DisposableBean实现方法 * @throws Exception */ public void destroy() throws Exception { } }
ServiceConfig
The method of real service released the following method which is inherited from the parent class's method ServiceConfig
if (!this.isDelay()) { this.export(); }