• Dubbo源码(十) 与Spring一起学习Dubbo里的Aware


    目录

    一、Spring

    1.BeanNameAware

    2. BeanClassLoaderAware

    3. ApplicationContextAware

    4. EnvironmentAware

    5. ApplicationEventPublisherAware

    6. aware注入时机

    二、Dubbo

    1. ExtensionAccessorAware

    三、小结


            现在很多同行做java开发几年了,被迫停留在curd的层面上"拧螺丝",对SpringAware可能只停留在怎么用的层面上,那我们用Spring时可以通过Aware能获取到容器工厂、应用上下文、Bean的类加载器等。

            那Spring 开发者为什么要设计这些Aware呢?那跟着这篇文章去一探究竟吧!      

            Spring 常见的一些Aware有 BeanNameAware、BeanClassLoaderAware、ApplicationContextAware、EnvironmentAware、ApplicationEventPublisherAware等。

            我在前文里写到Dubbo里的一些设计思想借鉴了Spring , 同样Dubbo 3.0里使用到了ScopeModelAware、ExtensionAccessorAware等,在初始化Extension Bean时设置了ExtensionAccessorAware, 让我们一起来看下aware的作用吧。

    一、Spring

    1.BeanNameAware

            获取到该Bean的name

    1. @DubboService
    2. public class DemoServiceImpl implements DemoService, BeanNameAware {
    3. @Override
    4. public String sayHello(String name) {
    5. System.out.println("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
    6. return "Hello " + name;
    7. }
    8. @Override
    9. public void setBeanName(String beanName) {
    10. System.out.println("获取到BeanName=" + beanName);
    11. }
    12. }

             在启动的时候获取到beanName: 

    2. BeanClassLoaderAware

            获取到加载Bean的类加载器,可用该加载器写业务代码。

    1. package org.apache.dubbo.springboot.demo.provider;
    2. import org.apache.dubbo.config.annotation.DubboService;
    3. import org.apache.dubbo.rpc.RpcContext;
    4. import org.apache.dubbo.springboot.demo.DemoService;
    5. import org.springframework.beans.factory.BeanClassLoaderAware;
    6. import org.springframework.beans.factory.BeanNameAware;
    7. @DubboService
    8. public class DemoServiceImpl implements DemoService, BeanNameAware, BeanClassLoaderAware {
    9. private ClassLoader classLoader;
    10. @Override
    11. public String sayHello(String name) {
    12. System.out.println("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
    13. try {
    14. Class clazz = classLoader.loadClass("org.apache.dubbo.springboot.demo.provider.Test01");
    15. Test01 test01 = (Test01) clazz.newInstance();
    16. test01.say();
    17. } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
    18. e.printStackTrace();
    19. }
    20. return "Hello " + name;
    21. }
    22. @Override
    23. public void setBeanName(String beanName) {
    24. System.out.println("获取到BeanName=" + beanName);
    25. }
    26. @Override
    27. public void setBeanClassLoader(ClassLoader classLoader) {
    28. this.classLoader = classLoader;
    29. }
    30. }

            获取到ClassLoader, 加载到Test01类后获取到指定对象:

    3. ApplicationContextAware

            获取到Spring应用的上下文applicationContext, 可以根据applicationContext去拿到某个bean。

            比如我新建一个Test02, 用@Component注解标记,表示交给spring 管理。

    1. package org.apache.dubbo.springboot.demo.provider;
    2. import org.apache.dubbo.config.annotation.DubboService;
    3. import org.apache.dubbo.rpc.RpcContext;
    4. import org.apache.dubbo.springboot.demo.DemoService;
    5. import org.springframework.beans.BeansException;
    6. import org.springframework.beans.factory.BeanClassLoaderAware;
    7. import org.springframework.beans.factory.BeanNameAware;
    8. import org.springframework.context.ApplicationContext;
    9. import org.springframework.context.ApplicationContextAware;
    10. @DubboService
    11. public class DemoServiceImpl implements DemoService, BeanNameAware, BeanClassLoaderAware, ApplicationContextAware {
    12. private ClassLoader classLoader;
    13. private ApplicationContext applicationContext;
    14. @Override
    15. public String sayHello(String name) {
    16. System.out.println("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
    17. try {
    18. Class clazz = classLoader.loadClass("org.apache.dubbo.springboot.demo.provider.Test01");
    19. Test01 test01 = (Test01) clazz.newInstance();
    20. test01.say();
    21. Test02 test02 = applicationContext.getBean(Test02.class);
    22. test02.say();
    23. } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
    24. e.printStackTrace();
    25. }
    26. return "Hello " + name;
    27. }
    28. @Override
    29. public void setBeanName(String beanName) {
    30. System.out.println("获取到BeanName=" + beanName);
    31. }
    32. @Override
    33. public void setBeanClassLoader(ClassLoader classLoader) {
    34. this.classLoader = classLoader;
    35. }
    36. @Override
    37. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    38. this.applicationContext = applicationContext;
    39. }
    40. }

    打印结果:

    4. EnvironmentAware

            新建一个EnvironmentAwareConfig类实现EnvironmentAware接口, 实现类需要是Bean, 即被Spring 容器管理的类。

            添加一个参数: -Dtest=testEnvironmentAware:

            我们可以在业务代码里根据environment对象获取到配置的参数。 

    1. package org.apache.dubbo.springboot.demo.provider;
    2. import org.springframework.context.EnvironmentAware;
    3. import org.springframework.core.env.Environment;
    4. import org.springframework.stereotype.Component;
    5. @Component
    6. public class EnvironmentConfig implements EnvironmentAware {
    7. @Override
    8. public void setEnvironment(Environment environment) {
    9. System.out.println("获取到属性: " + environment.getProperty("test", "nothing"));
    10. }
    11. }

            实际开发中,可以使用environment获取到启动入参。 

    5. ApplicationEventPublisherAware

            这个Aware是用来获取事件发布订阅的类ApplicationEventPublisher,利用applicationEventPublisher发布Spring 事件。

    1. package org.apache.dubbo.springboot.demo.provider.publish;
    2. import org.springframework.context.ApplicationEvent;
    3. import org.springframework.context.ApplicationEventPublisher;
    4. import org.springframework.context.ApplicationEventPublisherAware;
    5. import org.springframework.context.ApplicationListener;
    6. import org.springframework.stereotype.Component;
    7. @Component
    8. public class EventPublisher implements ApplicationEventPublisherAware {
    9. @Override
    10. public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
    11. applicationEventPublisher.publishEvent(new EventTest("test"));
    12. }
    13. public static class EventTest extends ApplicationEvent {
    14. public EventTest(Object source) {
    15. super(source);
    16. }
    17. }
    18. @Component
    19. public static class EventListener implements ApplicationListener {
    20. @Override
    21. public void onApplicationEvent(ApplicationEvent applicationEvent) {
    22. if (applicationEvent instanceof EventTest) {
    23. System.out.println("接收到事件====" + applicationEvent.getSource());
    24. }
    25. }
    26. }
    27. }

    打印结果: 

    6. aware注入时机

            以上的所有Aware都是Spring 提供给开发者使用的工具类,那他们是在Spring 什么时候注入的呢?

            看一下Spring 5.2+的代码, 他们其实是在postProccessBeforeInitialization()方法里注入的。

    1. //
    2. // Source code recreated from a .class file by IntelliJ IDEA
    3. // (powered by FernFlower decompiler)
    4. //
    5. package org.springframework.context.support;
    6. import java.security.AccessControlContext;
    7. import java.security.AccessController;
    8. import org.springframework.beans.BeansException;
    9. import org.springframework.beans.factory.config.BeanPostProcessor;
    10. import org.springframework.beans.factory.config.EmbeddedValueResolver;
    11. import org.springframework.context.ApplicationContextAware;
    12. import org.springframework.context.ApplicationEventPublisherAware;
    13. import org.springframework.context.ConfigurableApplicationContext;
    14. import org.springframework.context.EmbeddedValueResolverAware;
    15. import org.springframework.context.EnvironmentAware;
    16. import org.springframework.context.MessageSourceAware;
    17. import org.springframework.context.ResourceLoaderAware;
    18. import org.springframework.lang.Nullable;
    19. import org.springframework.util.StringValueResolver;
    20. class ApplicationContextAwareProcessor implements BeanPostProcessor {
    21. private final ConfigurableApplicationContext applicationContext;
    22. private final StringValueResolver embeddedValueResolver;
    23. public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
    24. this.applicationContext = applicationContext;
    25. this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    26. }
    27. @Nullable
    28. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    29. if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware)) {
    30. return bean;
    31. } else {
    32. AccessControlContext acc = null;
    33. if (System.getSecurityManager() != null) {
    34. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    35. }
    36. if (acc != null) {
    37. AccessController.doPrivileged(() -> {
    38. this.invokeAwareInterfaces(bean);
    39. return null;
    40. }, acc);
    41. } else {
    42. this.invokeAwareInterfaces(bean);
    43. }
    44. return bean;
    45. }
    46. }
    47. // 注入Aware
    48. private void invokeAwareInterfaces(Object bean) {
    49. if (bean instanceof EnvironmentAware) {
    50. ((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());
    51. }
    52. if (bean instanceof EmbeddedValueResolverAware) {
    53. ((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    54. }
    55. if (bean instanceof ResourceLoaderAware) {
    56. ((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);
    57. }
    58. if (bean instanceof ApplicationEventPublisherAware) {
    59. ((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);
    60. }
    61. if (bean instanceof MessageSourceAware) {
    62. ((MessageSourceAware)bean).setMessageSource(this.applicationContext);
    63. }
    64. if (bean instanceof ApplicationContextAware) {
    65. ((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
    66. }
    67. }
    68. }

     从invokeAwareInterfaces方法里得知aware的加载顺序:

    EnvironmentAware>ResourceLoaderAware>ApplicationEvenetPublisherAware>ApplicationContextAware 

    二、Dubbo

            ExtensionAccessorAware是为了SPI 扩展而设计的一个类,该了的作用提供方法实现类的ExtensionAccessor, 通过ExtensionAccessor可以获取到指定的SPI实现类。

    1. ExtensionAccessorAware

    1. /**
    2. * SPI extension can implement this aware interface to obtain appropriate {@link ExtensionAccessor} instance.
    3. */
    4. public interface ExtensionAccessorAware {
    5. void setExtensionAccessor(final ExtensionAccessor extensionAccessor);
    6. }

            该方法的调用时机是在Extension实例注入完成后执行。 

            方式一: 在ScopeBeanFactory注册Bean实例注入完成后,会执行PostProcessAfterInitialization()方法来初始化实例。 

    1. private void initializeBean(String name, Object bean) {
    2. checkDestroyed();
    3. try {
    4. // 设置一系列的aware
    5. if (bean instanceof ExtensionAccessorAware) {
    6. ((ExtensionAccessorAware) bean).setExtensionAccessor(extensionAccessor);
    7. }
    8. // 执行postProcessAfterInitialization(bean,name);
    9. for (ExtensionPostProcessor processor : extensionPostProcessors) {
    10. processor.postProcessAfterInitialization(bean, name);
    11. }
    12. } catch (Exception e) {
    13. throw new ScopeBeanException("register bean failed! name=" + name + ", type=" + bean.getClass().getName(), e);
    14. }
    15. }

            方式二: 在ExtensionLoader里执行InjectExtension(instance)方法后执行。

    1. @SuppressWarnings("unchecked")
    2. private T createExtension(String name, boolean wrap) {
    3. // 根据实现类名去加载所有的Spi,然后将实现类放入到内存里,然后返回实现类的Class
    4. Class clazz = getExtensionClasses().get(name);
    5. if (clazz == null || unacceptableExceptions.contains(name)) {
    6. throw findException(name);
    7. }
    8. try {
    9. T instance = (T) extensionInstances.get(clazz);
    10. if (instance == null) {
    11. extensionInstances.putIfAbsent(clazz, createExtensionInstance(clazz));
    12. instance = (T) extensionInstances.get(clazz);
    13. // 初始化之前
    14. instance = postProcessBeforeInitialization(instance, name);
    15. // 注入extension
    16. injectExtension(instance);
    17. // 初始化之后
    18. instance = postProcessAfterInitialization(instance, name);
    19. }
    20. }
    21. // ...
    22. }

            如果是ExensionAccessorAware那么就设置ExtensionAccessor。 

    1. @SuppressWarnings("unchecked")
    2. private T postProcessAfterInitialization(T instance, String name) throws Exception {
    3. //设置Aware
    4. if (instance instanceof ExtensionAccessorAware) {
    5. ((ExtensionAccessorAware) instance).setExtensionAccessor(extensionDirector);
    6. }
    7. if (extensionPostProcessors != null) {
    8. for (ExtensionPostProcessor processor : extensionPostProcessors) {
    9. instance = (T) processor.postProcessAfterInitialization(instance, name);
    10. }
    11. }
    12. return instance;
    13. }

           从代码里发现,Dubbo的ExtensionAccessorAware接口的设置在postProccessAfterInitialization方法之前,可以理解为Bean的初始化之前,我感觉此处的aware 初始化的时机设计类似于 Spring的aware。

    三、小结

            Aware的设计的初衷在于将应用的底层设计与业务剥离,开发者可以根据需求使用Aware来获取到指定对象,通过注入的对象添加一些需要的业务代码。

  • 相关阅读:
    【计算机组成原理】第六章 总线
    软件工程开发模式:从传统到现代的演进
    华为OD机考算法题:字符串比较
    元宇宙电商-NFG系统,让你的数字藏品得到保障
    vite打包流程和原理
    开学季:好好聊聊自己的大学生活
    DS18B20数字温度计 (一) 电气特性, 寄生供电模式和远距离接线
    Ajax——Ajax实现自动补全
    电脑正常开机后几分钟就黑屏一直循环怎么办?
    OneFlow源码解析:自动微分机制
  • 原文地址:https://blog.csdn.net/qq_33036061/article/details/127783110