小言_互联网的博客

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

308人阅读  评论(0)

目录

一、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来获取到指定对象,通过注入的对象添加一些需要的业务代码。


转载:https://blog.csdn.net/qq_33036061/article/details/127783110
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场