Spring BeanFactoryAware 解决 prototype 作用域失效问题
跟着孙哥学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 的,所以 userService 和 userService1 实际上是同一个实例。但是,由于我们在 register 方法中手动从 BeanFactory 中获取了 UserDAO 的新实例,所以每次调用 register 方法时,都会获取一个新的 UserDAO 实例,从而解决了 "prototype scope 失效" 的问题。
孙哥的讲解图例


浙公网安备 33010602011771号