看過上一講動態(tài)代理換種玩法咬荷,我們知道通過變形的動態(tài)代理膛薛,可以不需要目標(biāo)類刽射,就能生成代理類。
這種技術(shù)剃执,在我們今天的RPC框架中可以說被廣泛的使用誓禁。
下面我就通過我寫的一個簡單的RPC組件 來介紹它是如何實現(xiàn)。(注意:當(dāng)前版本可能為快照版本肾档,代碼在dev分支摹恰,未合并到master分支)
Spring的Autowired裝配
在Spring中,我們可以通過Autowired方式進行對象的裝配注入怒见,也就是說字段要被注入俗慈,需要被注解標(biāo)記。那么我們可以猜想遣耍,Spring一定有一段邏輯闺阱,來操作這個注入裝配的過程。
并且舵变,Spring為了好的可擴展性酣溃,以插件化的方式對裝配Bean的過程進行補充,這些插件就叫后處理器纪隙。而對Autowired進行組裝的后處理器就是:AutowiredAnnotationBeanPostProcessor赊豌,而具體的實現(xiàn)方法就是postProcessPropertyValues()。有興趣的可以自行閱讀绵咱。
RPC調(diào)用
我們知道本地調(diào)用肯定是通過對象完成碘饼,僅僅接口,如果沒有實例對象悲伶,是要報空指針的艾恼,但是RPC是遠(yuǎn)程的過程調(diào)用,是調(diào)用遠(yuǎn)程的對象麸锉,遠(yuǎn)程的方法蒂萎,本地是沒有實例對象存在的,那不就矛盾了嗎淮椰?
毫無疑問五慈,調(diào)用纳寂,肯定就有對象,只不過泻拦,這個對象我們沒有手工編碼毙芜,看到這里,可能有些同學(xué)已經(jīng)想到什么了争拐。沒錯腋粥,就是上節(jié)介紹的動態(tài)代理為接口偽裝出一個實現(xiàn)類。
對象可以通過動態(tài)代理生成架曹,那么如何把生成的對象如同Autowired注解標(biāo)記的字段一樣進行裝配呢隘冲?
實現(xiàn)裝配
既然我們知道了Autowired注解裝配的原理—通過后處理器完成。那么最簡單的方式绑雄,我們就仿照寫一個注解展辞,一個處理器不就成了。
注解
我們寫的注解是Reference万牺,在SpringBean中被使用罗珍,看下面代碼:
@RestController
public class DemoController {
@Reference(contract = IntfDemo.class, implCode = "abc")
private IntfDemo intfDemo;
@RequestMapping(path = "f1")
public String f1() {
return intfDemo.name();
}
}
裝配處理器
寫一個后處理,來處理被Reference注解標(biāo)記的字段脚粟,具體實現(xiàn)如下:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
/**
* 處理SpringBean的{@link Reference} 屬性的注入
*
* @author: guanjie
*/
@Component
@Slf4j
public class ReferenceBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, final Object bean, final String beanName) throws BeansException {
ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
FieldUtils.writeField(field, bean, ServerProxy.getProxy(field), true);
}
}, new ReflectionUtils.FieldFilter() {
@Override
public boolean matches(Field field) {
return field.isAnnotationPresent(Reference.class);
}
});
return pvs;
}
}
看上面功能代碼覆旱,不超過20行,就把這個功能完成了核无,而Spring會自動發(fā)現(xiàn)這個處理器扣唱,并在裝配階段對每個Bean使用。
ServerProxy.getProxy(field)和上節(jié)中生成代理類的方式幾乎一樣团南,只不過把處理邏輯換成了IO通信而已画舌。
原理懂了其實還是挺簡單的,想了解的更多已慢,可以拉下代碼研究曲聂,歡迎感興趣的同學(xué)一起來進行代碼的維護和后續(xù)的補充。