Spring扩展点之Aware接口族

淡淡的烟草味﹌ 2024-04-19 10:07 154阅读 0赞

Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContextAware,EnvironmentAware,BeanClassLoaderAware等

这些Aware的作用都可以从命名得知

Aware的处理

其中BeanNameAwareBeanClassLoaderAwareBeanFactoryAware这三个是直接在bean的初始化之前就处理了的,具体代码在AbstractAutowireCapableBeanFactory.initializeBean方法中:

  1. protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
  2. // 判断对象实现的接口类型,处理特定的三种接口类型:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。
  3. if (bean instanceof BeanNameAware) {
  4. ((BeanNameAware) bean).setBeanName(beanName);
  5. }
  6. if (bean instanceof BeanClassLoaderAware) {
  7. ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
  8. }
  9. if (bean instanceof BeanFactoryAware) {
  10. ((BeanFactoryAware) bean).setBeanFactory(this);
  11. }
  12. // 开始Bean初始化前处理、初始化、初始化后处理
  13. Object wrappedBean = bean;
  14. if (mbd == null || !mbd.isSynthetic()) {
  15. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  16. }
  17. try {
  18. invokeInitMethods(beanName, wrappedBean, mbd);
  19. }
  20. catch (Throwable ex) {
  21. throw new BeanCreationException(
  22. (mbd != null ? mbd.getResourceDescription() : null),
  23. beanName, "Invocation of init method failed", ex);
  24. }
  25. if (mbd == null || !mbd.isSynthetic()) {
  26. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  27. }
  28. return wrappedBean;
  29. }

除了这三种之外的那些Aware接口的实现就不太一样了,它们都是利用BeanPostProcessor接口完成的,关于BeanPostProcessor接口的原理可以这篇文章:Spring扩展点之BeanPostProcessor

ApplicationContextAware就是利用ApplicationContextAwareProcessor实现的:

  1. public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
  2. AccessControlContext acc = null;
  3. if (System.getSecurityManager() != null &&
  4. (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
  5. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
  6. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
  7. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  8. }
  9. if (acc != null) {
  10. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  11. //具体实现
  12. invokeAwareInterfaces(bean);
  13. return null;
  14. }, acc);
  15. }
  16. else {
  17. //具体实现
  18. invokeAwareInterfaces(bean);
  19. }
  20. return bean;
  21. }
  22. private void invokeAwareInterfaces(Object bean) {
  23. if (bean instanceof Aware) {
  24. if (bean instanceof EnvironmentAware) {
  25. ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
  26. }
  27. if (bean instanceof EmbeddedValueResolverAware) {
  28. ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
  29. }
  30. if (bean instanceof ResourceLoaderAware) {
  31. ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
  32. }
  33. if (bean instanceof ApplicationEventPublisherAware) {
  34. ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
  35. }
  36. if (bean instanceof MessageSourceAware) {
  37. ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
  38. }
  39. if (bean instanceof ApplicationContextAware) {
  40. ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  41. }
  42. }
  43. }

ApplicationContextAwareProcessor的注册奥秘在AbstractApplicationContext.prepareBeanFactory方法中:

  1. beanFactory.setBeanClassLoader(getClassLoader());
  2. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
  3. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  4. beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  5. beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  6. beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  7. beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

发表评论

表情:
评论列表 (有 0 条评论,154人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring-aware接口

    在springmvc中如果某个bean需要获取spring 的某些容器,可以通过实现其接口的方式,来获得,以此达到在Bean被初始后,能进行CRUD、数据源动态注入到全局应用等