dubbo版本:2.7.5
dubbo源码下载地址
自适应扩展点:
ExtensionLoader.getExtensionLoader(XXX.class).getAdaptiveExtension();
指定名称扩展点:
ExtensionLoader.getExtensionLoader(XXX.class).egtExtension(name);
激活扩展点:
ExtensionLoader.getExtensionLoader(XXX.class).getActivateExtension(url,key);
Service Provider Interface
jdk内置的一种服务提供发现机制
作用:服务的扩展实现
例如:数据库连接
jdk提供了java.sql.Driver接口
这个驱动类在jdk中没有实现,由不同数据库厂商实现
约定: 所有扩展点必须放在resources/META-INF/services目录下
SPI机制会扫描这个路径下的属性文件以完成加载
没有使用JDK内置的SPI机制
dubbo SPI相关逻辑被封装在ExtensionLoader类中
通过ExtensionLoader可以加载指定的实现类
2个规则:
1.需要在resources目录下创建任一目录结构:
META-INF/dubbo,META-INF/dubbo/internal,META-INF/service
在对应目录下创建全路径命名的文件
dubbo会去这3个目录下加载相应扩展点
2.内容是key-value形式的数据
key是字符串,value是一个对应扩展点实现
这样方式可以按照需要加载指定的实现类
步骤:
1.在一个依赖dubbo框架工程中,创建一个扩展点及一个实现
扩展点需要声明SPI注解
@SPI("myDriver")
public interface MyDriver {
String connect();
}
实现类
@Service
public class MyDriverImpl implements MyDriver {
@Override
public String connect() {
return "connect db success";
}
}
在resources/META-INF/dubbo目录下创建以spi接口命名的文件
com.zyl.dubbo.servive.spi.MyDriver
myDriver=com.zyl.dubbo.service.spi.MyDriver
创建测试类,获取指定名称扩展点实现
@SpringBootTest
@RunWith(SpringRunner.class)
public class DubboTest {
@Test
public void testSPI() {
ExtensionLoader<MyDriver> extensionLoader = ExtensionLoader.getExtensionLoader(MyDriver.class);
MyDriver myDriver = extensionLoader.getExtension("myDriver");//指定名称扩展点
System.out.println(myDriver.connect());
}
}
1.ExtensionLoader.getExtensionLoader()获得ExtensionLoader实例
先从缓存中获取与扩展类对应的ExtensionLoader
如果缓存未命中,则创建一个新的实例EXTENSION_LOADERS集合缓存起来
在ExtensionLoader构造方法中,初始化一个objectfACTORY,后续用到,暂时不管
ExtensionLoader
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
//省略前置判断
ExtensionLoader<T> loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
}
return loader;
}
//构造方法
private ExtensionLoader(Class<?> type) {
this.type = type;
this.objectFactory = type == ExtensionFactory.class ? null : (ExtensionFactory)getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
}
2.getExtension()获得指定方法名称的扩展点并返回
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
} else if ("true".equals(name)) {
//如果name=="true",返回一个默认的扩展实现
return this.getDefaultExtension();
} else {
//创建一个holder对象,用户缓存该扩展点的实例
Holder<Object> holder = this.getOrCreateHolder(name);
Object instance = holder.get();
//缓存不存在,则创建一个实例
if (instance == null) {
synchronized(holder) {
instance = holder.get();
if (instance == null) {
instance = this.createExtension(name);
holder.set(instance);
}
}
}
return instance;
}
}
步骤:先查缓存,缓存未命中,则创建一个扩展对象
createExtension():去指定的路径下查找name对应的扩展点实现,并且实例化后返回
private T createExtension(String name) {
//根据name返回扩展类
Class<?> clazz = (Class)this.getExtensionClasses().get(name);
if (clazz == null) {
throw this.findException(name);
} else {
try {
//从缓存中查找该类是否已经被初始化
T instance = EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = EXTENSION_INSTANCES.get(clazz);
}
//依赖注入
this.injectExtension(instance);
//通过wrapper进行包装
Set<Class<?>> wrapperClasses = this.cachedWrapperClasses;
Class wrapperClass;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for(Iterator var5 = wrapperClasses.iterator(); var5.hasNext(); instance = this.injectExtension(wrapperClass.getConstructor(this.type).newInstance(instance))) {
wrapperClass = (Class)var5.next();
}
}
return instance;
} catch (Throwable var7) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " + this.type + ") couldn't be instantiated: " + var7.getMessage(), var7);
}
}
}
getExtensionClasses()返回Map集合
key和value分别对应配置文件中的key和value
1.从缓存中获取已经被加载的扩展类
2.如果未命中缓存,则调用loadExtensionClasses()加载扩展类
private Map<String, Class<?>> getExtensionClasses() {
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
loadExtensionClasses()
loadDirectory()加载指定文件目录下的配置文件,根据传入的type全路径名找到对应的文件,解析内容后,保存加载到extensionClasses集合中
private Map<String, Class<?>> loadExtensionClasses() {
//获得当前扩展接口的默认扩展对象,并且缓存
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
//加载指定文件目录下的配置文件
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
return extensionClasses;
}
cacheDefaultExtensionName()
1.获得指定扩展接口的@SPI注解
2.得到@SPI注解中的名字,保存到cachedDefaultName属性中
private void cacheDefaultExtensionName() {
//获得type类声明的注解@SPI
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
//得到注解中定义的value值
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("More than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
if (names.length == 1) {
cachedDefaultName = names[0];
}
}
}
}
以dubbo中的org.apache.dubbo.rpc.protocol接口为例,在spi注解中有一个默认值dubbo
意味着如果没有显示指定协议类型, 默认采用dubbo协议发布服务
@SPI(""dubbo)
public interface Protocol{
//...
}
createExtension()
针对扩展类进行包装
用到装饰器模式,通过装饰器模式来增强扩展类的功能
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
dubbo源码包中META-INF/dubbo/internal目录下
org.apache.dubbo.rpv.Protocol文件
filter=org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
会对当前扩展点中原油的扩展类进行包装
假设当前扩展点是DubboProtocol
实际返回的扩展类对象可能为:
ProtocolFilterWrapper(ProtocolListenerWrapper(DubboOrotocol))
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
cachedWrapperClasses集合就是当前扩展点中适配的wrapper类
在loadDirectory()初始化的
loadDirectory()->loadResource()->loadClass()
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
//...
if (clazz.isAnnotationPresent(Adaptive.class)) {
cacheAdaptiveClass(clazz);
} else if (isWrapperClass(clazz)) {
cacheWrapperClass(clazz);
} else {
clazz.getconstructor();
//...
}
}
isWrapperClass为true,表示当前clazz是一个装饰器类
判断clazz类中是否存在一个带有扩展类的构造函数
public class ProtocolListenerWrapper implements Protocol {
private final Protocol protocol;
public ProtocolListenerWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
}
isWrappercalss()
private void cacheWrapperClass(Class<?> clazz) {
if (cachedWrapperClasses == null) {
cachedWrapperClasses = new ConcurrentHashSet<>();
}
cachedWrapperClasses.add(clazz);
}
得到这些装饰器类后,保存到cachedWrapperClasses集合
遍历集合,通过wrapper class.getconstructor(type).newInstance(instance)进行实例化
自适应扩展点(Adaptive)也可以理解为适配器扩展点
能够根据上下文动态匹配一个扩展类
ExtensionLoader.getExtensionLoader(class).getAdaptiveExtension();
通过@Adaptive注解声明,使用方式
1.@Adaptive注解定义在类上面,表示当前类为自适应扩展类
@Adaptive
public class AdaptiveCompiler implements Compiler {
@Override
public Class<?> compile(String code, ClassLoader classLoader) {
return null;
}
}
AdaptiveCompiler类就是自适应扩展类,通过ExtensionLoader.getExtensionLoader(Compiler.class).getAdaptiveExtension();
可以返回AdaptiveComipler类的实例
2.@Adaptive注解定义在方法层面,会通过动态代理的方式生成一个动态字节码,
进行自适应式配
@SPI("dubbo")
public interface Protocol {
int getDefaultPort();
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
@Adaptive
<T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
void destroy();
}
2个方法声明了@Adaptive注解,意味着这是一个自适应方法
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
prptocol实例,是一个动态代理类,实现方法级别自适应调用
调用export()方法时,会根据上下文自动匹配到某个具体的实现类export方法中
getAdaptiveExtension()
1.从缓存中获取自适应扩展点实例
2.如果缓存未命中,则通过createAdaptiveExtension()创建自适应扩展点
public T getAdaptiveExtension() {
//从缓存中获取自适应扩展点实例
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
//创建自适应扩展点实例,并且放置到缓存中
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
createAdaptiveExtension()
1.getAdaptiveExtensionClass()获得一个自适应扩展点实例
2.injectExtension()完成依赖注入
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
getAdaptiveExtensionclasses()
1.通过getExtensionClasses()加载当前传入类型的所有扩展点,缓存到一个集合中
2.如果cachedAdaptiveClass为空,则调用createAdaptiveExtensionClass()进行创建
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
createAdaptiveExtensionClass():动态字节码的生成和加载
1.code是一个动态拼接的类
2.通过complier进行动态编译
private Class<?> createAdaptiveExtensionClass() {
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
ClassLoader classLoader = findClassLoader();
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
}
Protocol$Adaptive是一个动态生成的自适应扩展类
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
protocol.export(...);
调用protocol.export()时,实际会调用Protocol#Adaptive类中export()方法,
根据dubbo服务配置的协议名称,通过getExtension()获得相应的扩展类
Protocol$Adaptive适配器模式,根据上下文信息自动适配到相应的协议扩展点来完成服务发布
动态地向某个对象提供它所需要的其他对象
通过Dependency Injection(依赖注入)来实现的
createExtension()
{
//...
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
//...
return instance;
} catch (Throwable t) {
//...
}
injectExtension()依赖注入实现
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (isSetter(method)) {
//遍历被加载的扩展类中所有set方法
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
//获得扩展类中方法的参数类型
Class<?> pt = method.getParameterTypes()[0];
//不是对象类型,跳过
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
//获得方法对应的属性名称
String property = getSetterProperty(method);
//根据class及name,使用自适应扩展点加载并且通过set方法赋值 Object object = objectFactory.getExtension(pt, property);
if (object != null) {
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("Failed to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
如果当前加载的扩展类中存在一个成员对象,并为它提供了set方法
就会通过自适应扩展点进行加载并赋值
把业务逻辑和功能逻辑分离,在运行期间或者类加载期间进行织入
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
AOP思想体现是基于Wrapper装饰器类实现对原有的扩展类instance进行包装
服务发布主要有以下几个步骤
1.添加dubbo-spring-boot-starter依赖
2.定义org.apache.dubbo.config.annotation.Service注解
3.声明@DubboComponentScan,用于扫描@Service注解
主要通过@Import导入一个DubboComponentScanRegistrar类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
DubboComponentScanRegistrar实现ImportBeanDefinitionRegistrar,并且重写registerBeanDefinitions()方法
1.获取扫描包的路径,在默认情况,扫描当前配置类所在包
2.注册@Service注解的解析类
3.注册@Reference注解的解析类
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//获取扫描包路径
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
//注册@Service的解析类
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
//注册@Reference的解析类
registerReferenceAnnotationBeanPostProcessor(registry);
}
ImportBeanDefinitionRegistrar是spring提供一种动态注入bean机制,类似ImportSelector
在registerBeanDefinitions()方法中,主要会实例化一些BeanDefinition注入Spring Ioc容器
registerServiceAnnotationBeanPostProcessor()方法:
把ServiceAnnotationBeanPostProcessor注册到容器
private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
builder.addConstructorArgValue(packagesToScan);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
//将beanDefinition注册到Ioc容器
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
@DubboComponentScan注入
ServiceAnnotationBeanPostProcessor和ReferenceAnnotationBeanPoastProcessor对象
ServiceAnnotationBeanPostProcessor解析@Service注解
ReferenceAnnotationBeanPostProcessor解析@Reference注解
核心逻辑:解析@Service注解
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
}
BeanDefinitionRegistryPostProcessor中定义的postProcessBeanDefinitionRegistry()
实现自定义的注册bean定义逻辑
1.调用registerBeans注册DubboBootstrapApplicationListener类
2.通过resolvePackagesToScan对packagesToScan参数进行去空格处理,并把配置文件中配置的扫描参数也一起处理一下
3.调用registerServerBeans()完成bean注册
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) {
registerServiceBeans(resolvedPackagesToScan, registry);
} else {
if (logger.isWarnEnabled()) {
logger.warn("packagesToScan is empty , ServiceBean registry will be ignored!");
}
}
}
核心逻辑registerServiceBeans()方法中,会查找需要扫描的指定包里有@Service注解的类
并注册成Bean
1.定义DubboClassPathDefinitionscanner扫描对象,扫描指定路径下的类,将符合条件的类装配Ioc容器中
2.BeanNameGenerator是Beans体系中比较重要的一个组件,通过一定的算法计算出需要装配的bean的name
3.addIncludeFilter设置scan的过滤条件,只扫描@Servioce注解装饰的类
4.遍历指定的包,通过findServiceBeanDefinitionHolders查找@Service注解修饰的类
5.通过registerServiceBean完成bean注册
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
//定义扫描对象
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
//beanName解析器
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
//添加过滤器,用于过滤@Service注解修饰的对象
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
scanner.addIncludeFilter(new AnnotationTypeFilter(com.alibaba.dubbo.config.annotation.Service.class));
for (String packageToScan : packagesToScan) {
scanner.scan(packageToScan);
//查找@Service修饰的类
Set<BeanDefinitionHolder> beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
//注册bean
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
beanDefinitionHolders +
" } were scanned under package[" + packageToScan + "]");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("No Spring Bean annotating Dubbo's @Service was found under package["
+ packageToScan + "]");
}
}
}
}
扫描指定路径下添加@Service注解的类,通过registerServiceBean注册ServiceBean
registerServiceBean(),ServiceBean是指org.apache.dubbo.config.spring.ServiceBean
1.resolveClass获取BeanDefinitionHolder中的Bean
2.findServiceAnnotation()会从beanClass类中找到@Service注解
3.getAnnotationAttributes获得注解中的属性,例如:loadBanance,cluster…
4.resolveServiceInterfaceClass()获得beanClass对应的接口定义
在@Service(interfaceClass=IHelloService.class)注解也可以声明interfaceClass
注解中声明的优先级最高,如果没有声明该属性,从父类中查找
5.buildServiceBeanDefinition用来构造org.apache.dubbo.config.spring.ServiceBean对象,每个dubbo服务的发布,最终都会出现一个ServiceBean
6.调用registerBeanDefinition将ServiceBean注入Ioc容器
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,
DubboClassPathBeanDefinitionScanner scanner) {
//获得需要发布的服务类
Class<?> beanClass = resolveClass(beanDefinitionHolder);
//得到该服务类上的注解
Annotation service = findServiceAnnotation(beanClass);
//获得注解中的属性,例如:cluster...
AnnotationAttributes serviceAnnotationAttributes = getAnnotationAttributes(service, false, false);
//获得服务类的接口声明
Class<?> interfaceClass = resolveServiceInterfaceClass(serviceAnnotationAttributes, beanClass);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
//构件ServiceBean
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, serviceAnnotationAttributes, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
String beanName = generateServiceBeanName(serviceAnnotationAttributes, interfaceClass);
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
//完成注册
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
if (logger.isInfoEnabled()) {
logger.info("The BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean has been registered with name : " + beanName);
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("The Duplicated BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean[ bean name : " + beanName +
"] was be found , Did @DubboComponentScan scan to same package in many times?");
}
}
}
并不是像普通的bean注入一样,直接将IHelloService对象的实例注入容器
而是注入一个ServiceBean对象,并不需要把自己注入spring Ioc容器中
需要把自己发布到网络上,提供给网络上的服务消费者来访问
当所有bean都处理完成之后,spring Ioc会发布一个事件
当触发这个事件时,会触发onContectRefreshedEvent方法
在这个方法中,可以看到dubbo服务启动的触发机制
dubboBootstrap.start()
进入org.apache.dubbo.config.ServiceConfig类中的export()方法
这个方法启动一个网络监听,从而实现服务发布