“載營(yíng)魄抱一臼闻,能無(wú)離乎?
專氣致柔今膊,能如嬰兒乎些阅?
滌除玄覽,能無(wú)疵乎斑唬?
愛(ài)民治國(guó),能無(wú)以智乎黎泣?
天門開(kāi)闔恕刘,能為雌乎?
明白四達(dá)抒倚,能無(wú)為乎褐着?
生之畜之,生而不有托呕,為而不恃含蓉,長(zhǎng)而不宰频敛,是謂玄德∠诳郏”[1]
Spring從誕生至今斟赚,ioc和aop一直都是其靈魂所在,至今我們使用spring依然依賴這兩大特性:依賴注入(ioc)差油、面向切面編程(aop)拗军。從設(shè)計(jì)模式上來(lái)講,卻極其簡(jiǎn)單蓄喇,無(wú)外乎工廠模式和代理模式发侵。
今天我們從dubbo的內(nèi)核源碼入手,來(lái)看看ioc和aop是如何影響著dubbo的框架設(shè)計(jì)妆偏。
ioc在dubbo中的應(yīng)用
dubbo的ioc主要體現(xiàn)在dubbo擴(kuò)展點(diǎn)加載的環(huán)節(jié)刃鳄,T injectExtension(T instance)方法中。該方法只在三個(gè)地方被使用:
createAdaptiveExtension()
--injectExtension((T) getAdaptiveExtensionClass().newInstance()) //為創(chuàng)建好的AdaptiveExtensionClass實(shí)例進(jìn)行屬性注入
createExtension(String name)
--injectExtension(instance) //為創(chuàng)建好的Extension實(shí)例進(jìn)行屬性注入
--injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)) //為創(chuàng)建好的wrapperClass實(shí)例進(jìn)行屬性注入
ExtensionLoader:
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (method.getName().startsWith("set") && method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {//一個(gè)參數(shù)的public的setXXX(T param)方法.例如,setName(String name)
Class<?> pt = method.getParameterTypes()[0];//參數(shù)param的類型T,eg.String
try {
String property = method.getName().length() > 3
? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";//獲取屬性名XXX, eg.name
Object object = objectFactory.getExtension(pt, property);//實(shí)例化參數(shù)
if (object != null) {
//執(zhí)行instance.method(object)方法,這里就是執(zhí)行instance的setter方法,進(jìn)行setter注入
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;
}
整個(gè)方法的作用就是通過(guò)instance對(duì)象實(shí)例的setter方法為instance的屬性賦值钱骂,完成setter注入叔锐,即IOC的最經(jīng)典的注入方式。
詳細(xì)步驟:
- 獲取instance的setter方法罐柳,通過(guò)setter方法獲取屬性名稱property和屬性類型pt(即paramType的簡(jiǎn)寫)
- 使用objectFactory創(chuàng)建一個(gè)property名稱(類型為pt)的對(duì)象實(shí)例
- 執(zhí)行instance的setter方法掌腰,注入property實(shí)例
其中,比較重要的就是:Object object = objectFactory.getExtension(pt, property);這個(gè)方法。其中的objectFactory=AdaptiveExtensionFactory實(shí)例从媚,其屬性factories = [SpringExtensionFactory實(shí)例, SpiExtensionFactory實(shí)例]泞坦。
看一下源碼:
private final List<ExtensionFactory> factories;
public <T> T getExtension(Class<T> type, String name) {
/**
* 先調(diào)用SpiExtensionFactory來(lái)實(shí)例化;
* 如果不行,再使用SpringExtensionFactory來(lái)實(shí)例化
*/
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
}
SpiExtensionFactory:
public class SpiExtensionFactory implements ExtensionFactory {
public <T> T getExtension(Class<T> type, String name) {
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {//type是接口且必須具有@SPI注解
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
if (loader.getSupportedExtensions().size() > 0) {//獲取type的所有ExtensionClasses實(shí)現(xiàn)的key
return loader.getAdaptiveExtension();//獲取type的裝飾類,如果有@Adaptive注解的類,則返回該類的實(shí)例,否則返回一個(gè)動(dòng)態(tài)代理類的實(shí)例(例如Protocol$Adpative的實(shí)例)
}
}
return null;
}
}
從這里我們可以看出dubbo-SPI的另外一個(gè)好處:可以為SPI實(shí)現(xiàn)類注入SPI的裝飾類或動(dòng)態(tài)代理類。
SpringExtensionFactory:
public class SpringExtensionFactory implements ExtensionFactory {
private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
public static void addApplicationContext(ApplicationContext context) {
contexts.add(context);
}
public static void removeApplicationContext(ApplicationContext context) {
contexts.remove(context);
}
@SuppressWarnings("unchecked")
public <T> T getExtension(Class<T> type, String name) {
for (ApplicationContext context : contexts) {
if (context.containsBean(name)) {//該context是否包含name的bean
Object bean = context.getBean(name);//獲取name的bean,如果是懶加載或多例的bean,此時(shí)會(huì)實(shí)例化name的bean
if (type.isInstance(bean)) {//如果obj的類型是type或其子類,與instanceof相同
return (T) bean;
}
}
}
return null;
}
}
aop在dubbo中的應(yīng)用
dubbo在獲取擴(kuò)展點(diǎn)時(shí)勺择,會(huì)有如下調(diào)用:
final Protocol dubboProtocol = loader.getExtension("dubbo");
調(diào)用層級(jí):
ExtensionLoader<T>.getExtension()
--createExtension(String name)
----getExtensionClasses().get(name)//獲取擴(kuò)展類
------loadExtensionClasses()
--------loadFile(Map<String, Class<?>> extensionClasses, String dir)
----injectExtension(instance);//ioc
----wrapper包裝;//aop
createExtension(String name),該方法源碼如下:
private T createExtension(String name) {
/** 從cachedClasses緩存中獲取所有的實(shí)現(xiàn)類map,之后通過(guò)name獲取到對(duì)應(yīng)的實(shí)現(xiàn)類的Class對(duì)象 */
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
/** 從EXTENSION_INSTANCES緩存中獲取對(duì)應(yīng)的實(shí)現(xiàn)類的Class對(duì)象,如果沒(méi)有,直接創(chuàng)建,之后放入緩存 */
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) {
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);
}
}
這里伦忠,先給出META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol內(nèi)容:
registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=com.alibaba.dubbo.rpc.support.MockProtocol
injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
memcached=com.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol
com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper和com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper省核,這兩個(gè)類不含有@Adaptive注解且具有含有Protocol的單參構(gòu)造器,符合這樣條件的會(huì)被列入AOP增強(qiáng)類昆码。放置在loader的私有屬性cachedWrapperClasses中气忠。
此時(shí)的loader:
- Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
- ExtensionFactory objectFactory = AdaptiveExtensionFactory(適配類)
factories = [SpringExtensionFactory實(shí)例, SpiExtensionFactory實(shí)例] - cachedWrapperClasses = [class ProtocolListenerWrapper, class ProtocolFilterWrapper]
再來(lái)看createExtension(String name)中的紅色部分,就是今天的重點(diǎn)AOP赋咽。如上所講旧噪,我在cachedWrapperClasses中緩存了兩個(gè)AOP增強(qiáng)類:class ProtocolListenerWrapper和class ProtocolFilterWrapper。
首先是獲取ProtocolListenerWrapper的單參構(gòu)造器脓匿,然后創(chuàng)建ProtocolListenerWrapper實(shí)例淘钟,最后完成對(duì)ProtocolListenerWrapper實(shí)例進(jìn)行屬性注入,注意此時(shí)的instance=ProtocolListenerWrapper實(shí)例陪毡,而不再是之前的DubboProtocol實(shí)例了米母。之后使用ProtocolFilterWrapper以同樣的方式進(jìn)行包裝勾扭,只是此時(shí)ProtocolFilterWrapper包裝的是ProtocolListenerWrapper實(shí)例。
-
老子《道德經(jīng)》第十章铁瞒,老子故里妙色,中國(guó)鹿邑。 ?