Spring BeanFactoryAware 解决 prototype 作用域失效问题

发布时间 2023-12-28 21:04:20作者: zzusjw

跟着孙哥学Spring,b站:https://www.bilibili.com/video/BV185411477k/?spm_id_from=333.337.search-card.all.click

在 Spring 中,如果一个 singleton bean 依赖了一个 prototype bean,那么这个 prototype bean 在初始化时只会被创建一次,这就是所谓的 "prototype scope 失效" 的问题。这是因为 singleton bean 在初始化时会创建并注入所有的依赖,而这个过程只会发生一次。

为了解决这个问题,我们可以使用 BeanFactoryAware 接口。BeanFactoryAware 是 Spring 提供的一个特殊接口,任何实现了这个接口的 bean 都可以获取到 BeanFactory 的引用。有了 BeanFactory 的引用,我们就可以在需要的时候,手动从 BeanFactory 中获取 prototype bean 的新实例。

以下是一个示例:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

public class UserServiceImpl implements UserService, BeanFactoryAware {
    private BeanFactory beanFactory;

    public UserServiceImpl() {
        System.out.println("UserServiceImpl.UserServiceImpl");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void register() {
        UserDAO userDAO = (UserDAO) beanFactory.getBean("userDAO");
        System.out.println("userDAO = " + userDAO);
        userDAO.save();
    }
}

在这个示例中,UserServiceImpl 实现了 BeanFactoryAware 接口,并重写了 setBeanFactory 方法,这样就可以获取到 BeanFactory 的引用。然后,在 register 方法中,我们手动从 BeanFactory 中获取了 UserDAO 的新实例。这样,每次调用 register 方法时,都会获取一个新的 UserDAO 实例,从而解决了 "prototype scope 失效" 的问题。

测试

我们可以通过以下测试代码来验证上述解决方案:

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
UserService userService = (UserService) beanFactory.getBean("userService");
UserService userService1 = (UserService) beanFactory.getBean("userService");

userService.register();
userService1.register();

在这段测试代码中,我们首先从 BeanFactory 中获取了两次 UserService 的实例,然后分别调用了它们的 register 方法。由于 UserService 是 singleton 的,所以 userServiceuserService1 实际上是同一个实例。但是,由于我们在 register 方法中手动从 BeanFactory 中获取了 UserDAO 的新实例,所以每次调用 register 方法时,都会获取一个新的 UserDAO 实例,从而解决了 "prototype scope 失效" 的问题。

孙哥的讲解图例

image