十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
Spring 有一个特点,就是创建出来的 Bean 对容器是无感的,一个 Bean 是怎么样被容器从一个 Class 整成一个 Bean 的,对于 Bean 本身来说是不知道的,当然也不需要知道,也就是 Bean 对容器的存在是无感的。

但是有时候我们可能会遇到一些场景,这些场景让我们去感知容器的存在,松哥举几个例子:
也就是说,虽然 Spring 中的 Bean 可以不用去感知 Spring 容器的存在,但是在实际开发中,我们往往还是需要 Spring 容器提供的各种能力,这样就迫使我们的 Bean 不得不去感知到 Spring 容器的存在。
那么 Spring 中的 Bean 如何感知到 Spring 容器的存在呢?
Aware 本身就有感知的意思。
Spring Aware 是 Spring 框架中的一个特性,它允许我们的应用程序或组件与 Spring 容器进行交互。当一个类实现了 Spring Aware 接口并注册到 Spring 容器中时,该类就能够感知到 Spring 容器的存在,并且可以获取容器的一些资源或进行一些特定的操作。
Spring Aware 接口包括了多个子接口,每个子接口对应于不同的 Spring 容器资源或功能。
Aware 的实现有很多,大的方向来说主要有如下一些:
图片
每一个 Aware 的作用如下:
通过实现这些接口,我们可以在应用程序中获取 Spring 容器提供的各种资源,并与容器进行交互,以实现更灵活和可扩展的功能。
举两个例子小伙伴们来感受下 Aware 的具体用法。
例如我想在 Bean 中感知到当前 Bean 的名字,那么我们可以按照如下方式来使用:
@Service
public class UserService implements BeanNameAware {
    private String beanName;
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }
    @Override
    public String toString() {
        return "UserService{" +
                "beanName='" + beanName + '\'' +
                '}';
    }
}让当前 bean 实现 BeanNameAware 接口,并重写 setBeanName 方法,这个方法会在 Spring 容器初始化 Bean 的时候自动被调用,我们就可以据此获取到 bean 的名称了。
再比如我想做一个工具 Bean,用来查找其他 Bean,那么我可以使用如下方式:
@Component
public class BeanUtils implements BeanFactoryAware {
    private static BeanFactory beanFactory;
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
    public static   T getBean(Class clazz) {
        return (T) beanFactory.getBean(clazz);
    }
}  让当前 Bean 实现 BeanFactoryAware 接口并重写 setBeanFactory 方法,在系统初始化当前 Bean 的时候,会自动调用 setBeanFactory 方法,进而将 beanFactory 变量传进来。
当 Spring 容器创建一个 Bean 的时候,大致的流程是创建实例对象 -> 属性填充 -> Bean 初始化。
最后这个 Bean 的初始化,就是调用 init 方法、afterPropertiesSet 方法以及 BeanPostProcessor 中的方法的,如下:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
 invokeAwareMethods(beanName, bean);
 Object wrappedBean = bean;
 if (mbd == null || !mbd.isSynthetic()) {
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 }
 try {
  invokeInitMethods(beanName, wrappedBean, mbd);
 }
 catch (Throwable ex) {
  throw new BeanCreationException(
    (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
 }
 if (mbd == null || !mbd.isSynthetic()) {
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }
 return wrappedBean;
}在这个方法一进来,首先有一个 invokeAwareMethods,这个就是用来触发 Aware 的,来看下:
private void invokeAwareMethods(String beanName, Object bean) {
 if (bean instanceof Aware) {
  if (bean instanceof BeanNameAware beanNameAware) {
   beanNameAware.setBeanName(beanName);
  }
  if (bean instanceof BeanClassLoaderAware beanClassLoaderAware) {
   ClassLoader bcl = getBeanClassLoader();
   if (bcl != null) {
    beanClassLoaderAware.setBeanClassLoader(bcl);
   }
  }
  if (bean instanceof BeanFactoryAware beanFactoryAware) {
   beanFactoryAware.setBeanFactory(AbstractAutowireCapableBeanFactory.this);
  }
 }
}小伙伴们可以看到,BeanNameAware、BeanClassLoaderAware 以及 BeanFactoryAware 这三种类型的 Aware 是在这里触发的。
每种 Aware 因为功能不同,因此作用的时机也不同。
invokeAwareMethods 方法执行完毕之后,接下来是执行 applyBeanPostProcessorsBeforeInitialization 方法,这个我们之前分析过,这个方法最终会触发 BeanPostProcessor#postProcessBeforeInitialization 方法的执行,而 BeanPostProcessor 有一个子类专门处理 Aware 的,就是 ApplicationContextAwareProcessor:
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
   bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
   bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware ||
   bean instanceof ApplicationStartupAware)) {
  return bean;
 }
 invokeAwareInterfaces(bean);
 return bean;
}
private void invokeAwareInterfaces(Object bean) {
 if (bean instanceof Aware) {
  if (bean instanceof EnvironmentAware environmentAware) {
   environmentAware.setEnvironment(this.applicationContext.getEnvironment());
  }
  if (bean instanceof EmbeddedValueResolverAware embeddedValueResolverAware) {
   embeddedValueResolverAware.setEmbeddedValueResolver(this.embeddedValueResolver);
  }
  if (bean instanceof ResourceLoaderAware resourceLoaderAware) {
   resourceLoaderAware.setResourceLoader(this.applicationContext);
  }
  if (bean instanceof ApplicationEventPublisherAware applicationEventPublisherAware) {
   applicationEventPublisherAware.setApplicationEventPublisher(this.applicationContext);
  }
  if (bean instanceof MessageSourceAware messageSourceAware) {
   messageSourceAware.setMessageSource(this.applicationContext);
  }
  if (bean instanceof ApplicationStartupAware applicationStartupAware) {
   applicationStartupAware.setApplicationStartup(this.applicationContext.getApplicationStartup());
  }
  if (bean instanceof ApplicationContextAware applicationContextAware) {
   applicationContextAware.setApplicationContext(this.applicationContext);
  }
 }
}大家看下,这七种类型的 Aware 是在这里被触发的。
另外像 ImportAware 是在 ImportAwareBeanPostProcessor#postProcessBeforeInitialization 方法中处理的;LoadTimeWeaverAware 是在 、LoadTimeWeaverAwareProcessor#postProcessBeforeInitialization 方法中处理的。
基本上,大部分的 Aware 接口都是在 BeanPostProcessor 中处理的。
            
            网页标题:如何让Bean深度感知Spring容器            
            URL链接:http://www.zsjierui.cn/article/dpcsoed.html