dubbo实现了自己的ioc注入,主要方法是ExtensionLoader里的injectExtension(T instance)方法。
private T injectExtension(T instance) {
try {
//objectFactory是dubbo的ioc容器 类型是ExtensionFactory 为dubbo的ioc提供所有的对象
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
Class<?> pt = method.getParameterTypes()[0];
try {
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
//set扩展名(Object object) 格式的方法 会根据类型和扩展名从 objectFactory中取得对象
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
//调用instance对象的moethod方法 并将object作为参数传入
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
public <T> T getExtension(Class<T> type, String name) {
//从SpiExtensionFactory或者SpringExtensionFactory读取对象
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
}
SpiExtensionFactory的获取
public <T> T getExtension(Class<T> type, String name) {
//判断接口是否被@spi注解 adaptive对象会根据dubbo的URL对象里面的值来选择接口的实现类对象
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
//如果类型支持的实现类大于0就返回extensionLoader的adaptive对象
if (loader.getSupportedExtensions().size() > 0) {
return loader.getAdaptiveExtension();
}
}
return null;
}
SpringExtensionFactory的获取
public <T> T getExtension(Class<T> type, String name) {
//从spring的context容器中根据类型和beanName查找对象
for (ApplicationContext context : contexts) {
if (context.containsBean(name)) {
Object bean = context.getBean(name);
if (type.isInstance(bean)) {
return (T) bean;
}
}
}
return null;
}
总的来说dubbo的ioc就是从dubbo的spi容器或者spring的容器中获取bean。
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
//这个地方是dubbo的aop简单实现 利用装饰模式对原有的类进行装饰 主要是ProtocolListenerWrapper(监听) ProtocolFilterWrapper(过滤)
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}