Aware和InitializingBean接口以及@Autowired注解失效分析

发布于:2025-05-13 ⋅ 阅读:(20) ⋅ 点赞:(0)

Aware 接口用于注入一些与容器相关信息,例如:

​ a. BeanNameAware 注入 Bean 的名字

​ b. BeanFactoryAware 注入 BeanFactory 容器

​ c. ApplicationContextAware 注入 ApplicationContext 容器

​ d. EmbeddedValueResolverAware 注入 解析器,解析${}

为什么有了@autowired还需要用Aware,因为autowired会存在失效的问题

在 Spring 框架里,@Autowired和Aware接口有着不同的设计目的,它们并非简单的替代关系。下面详细分析它们的差异以及@Autowired可能失效的场景。

1. @Autowired 的工作原理与局限
@Autowired借助依赖注入(DI)的方式,把 Spring 容器中的 bean 自动注入到目标组件里。不过,它存在以下几方面的限制:

生命周期的制约:@Autowired主要在 bean 的实例化和属性填充阶段发挥作用。要是你需要在 bean 初始化的更早阶段获取某些资源,@Autowired就无法满足需求了。
静态环境的不适用:由于静态变量或方法不属于某个具体的 bean 实例,所以@Autowired不能直接对静态字段进行注入。
ApplicationContext 依赖问题:如果要获取ApplicationContext本身,使用@Autowired会形成循环依赖,比如在自定义 bean 处理器中就可能遇到这种情况。

2. Aware 接口的作用
Aware接口是 Spring 提供的一种回调机制,它允许 bean 在初始化过程中获取容器的特定资源。常见的Aware接口有:

ApplicationContextAware:能获取ApplicationContext。
BeanNameAware:可以获取当前 bean 的名称。
EnvironmentAware:能够获取环境配置信息。

简单的来说

@Autowired的解析依赖于 bean 后处理器,属于扩展功能。也就是说@Autowired注解的功能实现是借助 Spring 的
bean 后处理器来完成的,在 bean 的生命周期中,@Autowired的解析处理是在特定的扩展流程里进行的。

Aware 接口属于内置功能,无需添加任何扩展 Spring 就能识别。这意味着在 Spring 容器的核心流程中,Aware
接口相关方法会被调用,在某些场景下,因为@Autowired属于扩展功能,可能会在一些特殊情况下失效,而作为内置功能的 Aware
接口不会出现这种问题。例如在某些场景下,使用 Aware 接口注入 ApplicationContext
能成功,但是使用@Autowired注入 ApplicationContext 却会失败 。

public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
    @Override
    public void setBeanName(String name) {
        log.debug("当前bean:" + this + ",实现 BeanNameAware 调用的方法,名字叫:" + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.debug("当前bean:" + this + ",实现 ApplicationContextAware 调用的方法,容器叫:" + applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.debug("当前bean:" + this + ",实现 InitializingBean 调用的方法,初始化");
    }

    @Autowired
    public void aaa(ApplicationContext applicationContext) {
        log.debug("当前bean:" + this +",使用 @Autowired 容器是:" + applicationContext);
    }

    @PostConstruct
    public void init() {
        log.debug("当前bean:" + this + ",使用 @PostConstruct 初始化");
    }
}

public class TestAwareAndInitializingBean {
    @Test
    public void testAware1() throws Exception {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("myBean", MyBean.class);

        context.refresh();

        context.close();
    }
}

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到