Motan集成Springboot机制源码简析

发布时间:2024年01月05日

上一篇看了下Springboot启动原理。我们知道了,Springboot在启动过程中,如何实现BeanDefinition–>Bean–>Proxy的过程。今天我们就从RPC框架Motan源码来看看,Motan是如何集成到Springboot中的。

思路分析:

  1. 首先Motan应该要能将@MotanService注解的类扫描到BeanFactory中。
  2. Motan应该要能对@MotanRefer注解的属性,进行代理,使其在调用方法的时候,能请求远端。
  3. Motan应该要能将@MotanService注解的类,暴露注册到服务中心。

在源码的springsupport包下面, 我们重点看AnnotationBean这个类。由这个类出发,完成了上述功能。

代码行格式说明:方法名()[实现类]{方法内部截取} 。为简明,方法参数部分省略。

扫描:

AnnotationBean 实现了BeanPostProcessor。 在Springboot启动过程中,在refreshContext() 执行过程中,调用 invokeBeanFactoryPostProcessors() 。就会执行AnnotationBean 的postProcessBeanFactory() 方法。

@Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){

        if (beanFactory instanceof BeanDefinitionRegistry) {
            try {
                Object scanner = scannerClass.getConstructor(new Class<?>[]{BeanDefinitionRegistry.class, boolean.class})
                        .newInstance(new Object[]{(BeanDefinitionRegistry) beanFactory, true});
                // add filter
                Class<?> filterClass = ClassUtils.forName();
				// 需要扫描带@MotanService注解的类
                Object filter = filterClass.getConstructor(Class.class).newInstance(MotanService.class);

                Method scan = scannerClass.getMethod("scan", new Class<?>[]{String[].class});
				// 从配置的annotationPackages开始扫描
                scan.invoke(scanner, new Object[]{annotationPackages});
            } 
        }
    }

对调用代理

在postProcessBeforeInitialization方法中实现

@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
          Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            try {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                // 找出@MontanRefer注解的字段
                MotanReferer reference = field.getAnnotation(MotanReferer.class);
                if (reference != null) {
                	// 这一行refer就是去做代理
                    Object value = refer(reference, field.getType());
                    if (value != null) {
                    // 将实现了调用代理类的字段赋值
                        field.set(bean, value);
                    }
                }
            } 
        }
        return bean;
    }

我们已经看到是从refer()方法进入,去构造代理的。那么我们继续看如何实现代理的

 
	private <T> Object refer(MotanReferer reference, Class<?> referenceClass) {
		return referenceConfig.getRef()[ReferConfig]{
			initRef()[ReferConfig]{
				// 这里从Zk获取了服务端的注册信息。假设我们是从AccountBusiness远端调用UserBusiness。那么这里就是将UserBusiness集群注册信息获取到
				ClusterSupport<T> clusterSupport = createClusterSupport(refUrl, configHandler);
				// 这里就是具体的代理实现了
				ref = configHandler.refer(interfaceClass, clusters, proxy)[SimpleConfigHandler]{
					return proxyFactory.getProxy(interfaceClass, clusters)
				};
			}
		};
	}

暴露本地服务

在postProcessAfterInitialization方法中实现

public Object postProcessAfterInitialization(Object bean, String beanName) throws
			BeansException {
		MotanService service = clazz.getAnnotation(MotanService.class);
		if (service != null) {
			serviceConfig.setRef(bean);
			// 暴露或者注册到注册中心
			serviceConfig.export();
		}
		return bean;
	}

总结:

其实RPC框架的实现,说难也难说简单也简单。难的是你的设计将如何面对实际中的复杂应用场景;简单的是其思想可以仅仅浓缩成一行方法调用。这篇文章,我们只是讲了Motan如何集成到Springboot的。但是还有很多RPC框架实现难点,我们并没有说明。如:HA,路由,熔断,序列化等。但只要我们知道了设计思路,都可以从源码中清晰的看到别人如何实现的。

文章来源:https://blog.csdn.net/qq_14853889/article/details/135414560
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。