@Override
protected Object doGetInjectedBean(AnnotationAttributes attributes, Object bean, String beanName, Class<?> injectedType,
InjectionMetadata.InjectedElement injectedElement) throws Exception {
/**
* The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
*/
String referencedBeanName = buildReferencedBeanName(attributes, injectedType);
/**
* The name of bean that is declared by {@link Reference @Reference} annotation injection
*/
String referenceBeanName = getReferenceBeanName(attributes, injectedType);
ReferenceBean referenceBean = buildReferenceBeanIfAbsent(referenceBeanName, attributes, injectedType);
boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);
registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);
cacheInjectedReferenceBean(referenceBean, injectedElement);
return getOrCreateProxy(referencedBeanName, referenceBean, localServiceBean, injectedType);
}
创建ReferencedBean名称(被引用)和ReferenceBean名称(引用)
/**
* @param attributes the attributes of {@link Reference @Reference}
* @param serviceInterfaceType the type of Dubbo's service interface
* @return The name of bean that annotated Dubbo's {@link Service @Service} in local Spring {@link ApplicationContext}
*/
private String buildReferencedBeanName(AnnotationAttributes attributes, Class<?> serviceInterfaceType) {
ServiceBeanNameBuilder serviceBeanNameBuilder = create(attributes, serviceInterfaceType, getEnvironment());
return serviceBeanNameBuilder.build();
}
首先创建一个ServiceBeanNameBuilder对象,用于创建ServiceBean的名称
private ServiceBeanNameBuilder(AnnotationAttributes attributes, Class<?> defaultInterfaceClass, Environment environment) {
// 解析名称
this(resolveInterfaceName(attributes, defaultInterfaceClass), environment);
// 解析group
this.group(getAttribute(attributes,"group"));
// 解析版本
this.version(getAttribute(attributes,"version"));
}
解析属性interfaceClass和interfaceName
如果没有这些参数配置,最后取接口的名称
然后解析group和version
最后根据解析到的各种属性创建名称
public String build() {
StringBuilder beanNameBuilder = new StringBuilder("ServiceBean");
// Required
append(beanNameBuilder, interfaceClassName);
// Optional
append(beanNameBuilder, version);
append(beanNameBuilder, group);
// Build and remove last ":"
String rawBeanName = beanNameBuilder.toString();
// Resolve placeholders
return environment.resolvePlaceholders(rawBeanName);
}
可以看出这个名称是由ServiceBean:接口类名称:version:group四个部分组成的。如果version和group参数都没有配置,则只包含前两个部分。如果存在占位符,最后也会解析占位符。
上面通过@Reference
注解参数和Dubbo的服务接口获取一个被引用Bean名称,下面会根据@Reference
注解上面是否存在id属性再获取一个引用Bean名称。
/**
* Get the bean name of {@link ReferenceBean} if {@link Reference#id() id attribute} is present,
* or {@link #generateReferenceBeanName(AnnotationAttributes, Class) generate}.
*
* @param attributes the {@link AnnotationAttributes attributes} of {@link Reference @Reference}
* @param interfaceClass the {@link Class class} of Service interface
* @return non-null
* @since 2.7.3
*/
private String getReferenceBeanName(AnnotationAttributes attributes, Class<?> interfaceClass) {
// id attribute appears since 2.7.3
String beanName = getAttribute(attributes, "id");
if (!hasText(beanName)) {
beanName = generateReferenceBeanName(attributes, interfaceClass);
}
return beanName;
}
构建ReferenceBean
首先考虑从缓存中获取,如果缓存中不存在则进行创建,主要是通过ReferenceBeanBuilder这个类来实现的。
/**
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
*/
public static final String BEAN_NAME = "referenceAnnotationBeanPostProcessor";
/**
* Cache size
*/
private static final int CACHE_SIZE = Integer.getInteger(BEAN_NAME + ".cache.size", 32);
// 本地缓存
private final ConcurrentMap<String, ReferenceBean<?>> referenceBeanCache =
new ConcurrentHashMap<>(CACHE_SIZE);
private ReferenceBean buildReferenceBeanIfAbsent(String referenceBeanName, AnnotationAttributes attributes,
Class<?> referencedType)
throws Exception {
ReferenceBean<?> referenceBean = referenceBeanCache.get(referenceBeanName);
if (referenceBean == null) {
ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder
// 根据参数和上下文构建一个Builder独享
.create(attributes, applicationContext)
// 指定被引用的类型
.interfaceClass(referencedType);
// 进行构造
referenceBean = beanBuilder.build();
// 添加到缓存当中
referenceBeanCache.put(referenceBeanName, referenceBean);
} else if (!referencedType.isAssignableFrom(referenceBean.getInterfaceClass())) {
throw new IllegalArgumentException("reference bean name " + referenceBeanName + " has been duplicated, but interfaceClass " +
referenceBean.getInterfaceClass().getName() + " cannot be assigned to " + referencedType.getName());
}
return referenceBean;
}
首先根据注解属性和Spring容器构建一个AnnotatedInterfaceConfigBeanBuilder对象(ReferenceBeanBuilder)
设置接口类型
首先检查依赖,目前为空实现
执行doBuild,构造一个ReferenceBean对象
@Override
protected ReferenceBean doBuild() {
return new ReferenceBean<Object>();
}
ReferenceBean是一个比较复杂的类,下面是它的类继承结构
除此之外,还实现了Spring的一些接口,最重要的就是FactoryBean和InitializingBean
在构造的时候首先会执行父类的构造,比如ReferenceConfig
其中就包括以下的属性,通过SPI机制获取协议实现
/**
* The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios.
* A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}.
* For example:
*
* <li>when the url is registry://224.5.6.7:1234/org.apache.dubbo.registry.RegistryService?application=dubbo-sample,
* then the protocol is <b>RegistryProtocol</b></li>
*
* <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
* the protocol is <b>DubboProtocol</b></li>
* <p>
* Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
* layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
*/
private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
首先获取一个ExtensionLoader,参数为Protocol.class
又会触发获取一个ExtensionLoader,参数为ExtensionFactory.class
如果是ExtensionFactory类型的话,其中的objectFactory属性为null,结束继续创建
如果不是ExtensionFactory类型的话,则使用ExtensionFactory对应的ExtensionLoader去获取一个实现类
首先读取缓存,没有则创建一个,然后再缓存
public T getAdaptiveExtension() {
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError != null) {
throw new IllegalStateException("Failed to create adaptive instance: " +
createAdaptiveInstanceError.toString(),
createAdaptiveInstanceError);
}
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);
}
}
}
}
return (T) instance;
}
@SuppressWarnings("unchecked")
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);
}
}
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
按照相同模式
/**
* The {@link Cluster}'s implementation with adaptive functionality, and actually it will get a {@link Cluster}'s
* specific implementation who is wrapped with <b>MockClusterInvoker</b>
*/
private static final Cluster CLUSTER = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();
/**
* A {@link ProxyFactory} implementation that will generate a reference service's proxy,the JavassistProxyFactory is
* its default implementation
*/
private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
构造完成之后需要进行配置
protected void configureBean(C configBean) throws Exception {
preConfigureBean(attributes, configBean);
configureRegistryConfigs(configBean);
configureMonitorConfig(configBean);
configureApplicationConfig(configBean);
configureModuleConfig(configBean);
postConfigureBean(attributes, configBean);
}
@Override
protected void preConfigureBean(AnnotationAttributes attributes, ReferenceBean referenceBean) {
Assert.notNull(interfaceClass, "The interface class must set first!");
DataBinder dataBinder = new DataBinder(referenceBean);
// Register CustomEditors for special fields
dataBinder.registerCustomEditor(String.class, "filter", new StringTrimmerEditor(true));
dataBinder.registerCustomEditor(String.class, "listener", new StringTrimmerEditor(true));
dataBinder.registerCustomEditor(Map.class, "parameters", new PropertyEditorSupport() {
@Override
public void setAsText(String text) throws java.lang.IllegalArgumentException {
// Trim all whitespace
String content = StringUtils.trimAllWhitespace(text);
if (!StringUtils.hasText(content)) { // No content , ignore directly
return;
}
// replace "=" to ","
content = StringUtils.replace(content, "=", ",");
// replace ":" to ","
content = StringUtils.replace(content, ":", ",");
// String[] to Map
Map<String, String> parameters = CollectionUtils.toStringMap(commaDelimitedListToStringArray(content));
setValue(parameters);
}
});
// Bind annotation attributes
dataBinder.bind(new AnnotationPropertyValuesAdapter(attributes, applicationContext.getEnvironment(), IGNORE_FIELD_NAMES));
}
配置RegistryConfig,此处为null
配置MonitorConfig,此处为null
配置ApplicationConfig,此处为null
配置ModuleConfig,此处为null
根据配置参数,后置处理
@Override
protected void postConfigureBean(AnnotationAttributes attributes, ReferenceBean bean) throws Exception {
// 设置Spring的上下文 并将上下文对象引入到dubbo中
bean.setApplicationContext(applicationContext);
configureInterface(attributes, bean);
configureConsumerConfig(attributes, bean);
configureMethodConfig(attributes, bean);
bean.afterPropertiesSet();
}
根据注解参数配置Interface信息,如果参数中没有,则读取原来的interfaceClass属性
配置消费者信息,此处为null
private void configureConsumerConfig(AnnotationAttributes attributes, ReferenceBean<?> referenceBean) {
String consumerBeanName = getAttribute(attributes, "consumer");
ConsumerConfig consumerConfig = getOptionalBean(applicationContext, consumerBeanName, ConsumerConfig.class);
referenceBean.setConsumer(consumerConfig);
}
解析参数methods
void configureMethodConfig(AnnotationAttributes attributes, ReferenceBean<?> referenceBean) {
Method[] methods = (Method[]) attributes.get("methods");
List<MethodConfig> methodConfigs = MethodConfig.constructMethodConfig(methods);
if (!methodConfigs.isEmpty()) {
referenceBean.setMethods(methodConfigs);
}
}
调用Bean的afterPropertiesSet方法
public void afterPropertiesSet() throws Exception {
// Initializes Dubbo's Config Beans before @Reference bean autowiring
prepareDubboConfigBeans();
// lazy init by default.
if (init == null) {
init = false;
}
// 通常为false
// eager init if necessary.
if (shouldInit()) {
getObject();
}
}
准备dubbo的各种配置Bean,即进行初始化
private void prepareDubboConfigBeans() {
beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class);
beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class);
beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class);
beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class);
beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class);
beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class);
beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class);
beansOfTypeIncludingAncestors(applicationContext, ConfigCenterBean.class);
beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class);
beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class);
beansOfTypeIncludingAncestors(applicationContext, SslConfig.class);
}
通过以上步骤,完成bean的创建,然后放到缓存当中
注册ReferenceBean
判断目标引用bean是否存在,通常为false
/**
* Is Local Service bean or not?
*
* @param referencedBeanName the bean name to the referenced bean
* @return If the target referenced bean is existed, return <code>true</code>, or <code>false</code>
* @since 2.7.6
*/
private boolean isLocalServiceBean(String referencedBeanName, ReferenceBean referenceBean, AnnotationAttributes attributes) {
return existsServiceBean(referencedBeanName) && !isRemoteReferenceBean(referenceBean, attributes);
}
/**
* Check the {@link ServiceBean} is exited or not
*
* @param referencedBeanName the bean name to the referenced bean
* @return if exists, return <code>true</code>, or <code>false</code>
* @revised 2.7.6
*/
private boolean existsServiceBean(String referencedBeanName) {
return applicationContext.containsBean(referencedBeanName) &&
applicationContext.isTypeMatch(referencedBeanName, ServiceBean.class);
}
注册一个ReferenceBean
/**
* Register an instance of {@link ReferenceBean} as a Spring Bean
*
* @param referencedBeanName The name of bean that annotated Dubbo's {@link Service @Service} in the Spring {@link ApplicationContext}
* @param referenceBean the instance of {@link ReferenceBean} is about to register into the Spring {@link ApplicationContext}
* @param attributes the {@link AnnotationAttributes attributes} of {@link Reference @Reference}
* @param localServiceBean Is Local Service bean or not
* @param interfaceClass the {@link Class class} of Service interface
* @since 2.7.3
*/
private void registerReferenceBean(String referencedBeanName, ReferenceBean referenceBean,
AnnotationAttributes attributes,
boolean localServiceBean, Class<?> interfaceClass) {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// @Reference com.xquant.platform.test.trade.common.FacadeTradeTestService
String beanName = getReferenceBeanName(attributes, interfaceClass);
if (localServiceBean) { // If @Service bean is local one
/**
* Get the @Service's BeanDefinition from {@link BeanFactory}
* Refer to {@link ServiceAnnotationBeanPostProcessor#buildServiceBeanDefinition}
*/
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) beanFactory.getBeanDefinition(referencedBeanName);
RuntimeBeanReference runtimeBeanReference = (RuntimeBeanReference) beanDefinition.getPropertyValues().get("ref");
// The name of bean annotated @Service
String serviceBeanName = runtimeBeanReference.getBeanName();
// register Alias rather than a new bean name, in order to reduce duplicated beans
beanFactory.registerAlias(serviceBeanName, beanName);
} else { // Remote @Service Bean
if (!beanFactory.containsBean(beanName)) {
// 注册一个引用bean
beanFactory.registerSingleton(beanName, referenceBean);
}
}
}
创建代理
/**
* Get or Create a proxy of {@link ReferenceBean} for the specified the type of Dubbo service interface
*
* @param referencedBeanName The name of bean that annotated Dubbo's {@link Service @Service} in the Spring {@link ApplicationContext}
* @param referenceBean the instance of {@link ReferenceBean}
* @param localServiceBean Is Local Service bean or not
* @param serviceInterfaceType the type of Dubbo service interface
* @return non-null
* @since 2.7.4
*/
private Object getOrCreateProxy(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean,
Class<?> serviceInterfaceType) {
if (localServiceBean) { // If the local @Service Bean exists, build a proxy of Service
return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
newReferencedBeanInvocationHandler(referencedBeanName));
} else {
exportServiceBeanIfNecessary(referencedBeanName); // If the referenced ServiceBean exits, export it immediately
return referenceBean.get();
}
}
进行服务bean的暴露 但是不存在 实际未进行export
private void exportServiceBeanIfNecessary(String referencedBeanName) {
// 由于不存在 返回false
if (existsServiceBean(referencedBeanName)) {
ServiceBean serviceBean = getServiceBean(referencedBeanName);
if (!serviceBean.isExported()) {
serviceBean.export();
}
}
}