突发奇想想给练手的Rpc项目中的服务免去配置动态代理的过程,直接使用AutoWired注入
这是没有配置前使用的流程
RpcClientProxy rpcClientProxy =new RpcClientProxy(Service.class);
Service service= rpcClientProxy.getProxy(Service.class);
System.out.println(service.caculate(1,1));
使用将动态代理放入到容器后自动注册
@Controller
@RequestMapping("/nagi-rpc")
@CrossOrigin(origins = {"*"}, allowCredentials = "true")
public class NodeController {
@Autowired
NodeService nodeService;
@Autowired
Caculate caculate;
@RequestMapping("/list")
@ResponseBody
public List<ServiceNode> getServiceLists() throws Exception {
return nodeService.getNodes();
}
@RequestMapping("/change")
@ResponseBody
public String changeStatus(String ServiceName) throws Exception {
nodeService.changeStatus(ServiceName);
return "success";
}
@RequestMapping("/test")
@ResponseBody
public String test(){
return caculate.caculate(1,1);
}
在test中可以直接调用服务了(Caculate)
具体实现主要还是通过Spring对Ioc容器提供的扩展点
实现类
//用于将带@RpcService的接口自动注册到Ioc容器中,并将其实现设为动态代理实现
@Component
public class ProxyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor{
//带@RpcService的类
Set<Class<?>> classes;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
//设置扫包路径
this.classes=getRpcServiceClasses("");
for(Class<?> clazz:classes){
//生成接口的BeanDefinition
BeanDefinitionBuilder builder=BeanDefinitionBuilder.genericBeanDefinition(clazz);
GenericBeanDefinition definition= (GenericBeanDefinition) builder.getRawBeanDefinition();
//设置构造方法,不然后面FactoryBean无法正常调用
definition.getConstructorArgumentValues().addGenericArgumentValue(clazz);
//将类设为FactoryBean
definition.setBeanClass(ServiceFactory.class);
//将BeanDefinition注册到容器
registry.registerBeanDefinition(definition.getBeanClassName(), definition);
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
//扫包找到带对应注释的类
private Set<Class<?>> getRpcServiceClasses(String basePackage){
Reflections reflections=new Reflections(basePackage,new TypeAnnotationsScanner(),new SubTypesScanner());
return reflections.getTypesAnnotatedWith(RpcService.class);
}
}
实习了BeanDefinitionRegistryPostProcessor接口的组价可以在bean加载进Ioc容器还未实例化前执行扩展,比如这里又通过扫描包将包含了@RpcService注释的接口注册进容器,并将类设置为
//代替Service在Bean中的类,会调用getObject返回代理类
public class ServiceFactory<T> implements FactoryBean<T> {
private Class<T> interfaceType;
public ServiceFactory(Class<T> interfaceType) {
this.interfaceType = interfaceType;
}
@Override
public T getObject() throws Exception {
RpcClientProxy rpcClientProxy =new RpcClientProxy(interfaceType);
return (T) rpcClientProxy.getProxy(interfaceType);
}
@Override
public Class<?> getObjectType() {
return interfaceType;
}
@Override
public boolean isSingleton() {
return true;
}
}
这里获得bean时便会调用getObject方法或者对应代理对象,也就可以将动态代理
注入了
代理对象
@Data
@AllArgsConstructor
public class RpcClientProxy implements InvocationHandler {
/**
* 被代理类
*/
private final Class<?> serviceClass;
public <T> T getProxy(Class<?> clazz){
return (T) Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},this);
}
/***
*
* @param proxy 这个proxy的作用是啥
* @param method
* @param args
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
RpcRequest request =new RpcRequest(serviceClass.getName(),method.getName(), method.getParameterTypes(), args);
RpcClientService rpcClientService = ExtensionLoader.getExtensionLoader(RpcClientService.class).getExtension("RpcClientService");
RpcResponse response;
if(serviceClass.getAnnotation(Dispensable.class)!=null){
response = (RpcResponse) rpcClientService.service(request,true);
}
else response = (RpcResponse) rpcClientService.service(request);
if(response.getAns()==null){
return "服务繁忙请稍后再试";
}
return response.getAns();
}
}