一、问题
在scope=singleton的单例对象中注入scope=prototype的多例对象会注入失效,每次调用多例对象不会创建新的,因为单例对象只创建一次,所以每次获取的多例对象都是同一个;但是直接Spring容器中获取对象,每次获取的对象是不同的。
例子:
applicationContext.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDao" class="edu.hzb.first.UserDaoImpl" scope="prototype"/>
<bean id="userService" class="edu.hzb.first.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
</beans>
UserDao代码
public interface UserDao {
public void save();
}
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("UserDaoImpl.save");
}
}
UserService代码
public interface UserService {
public void register();
}
public class UserServiceImpl implements UserService {
private UserDao userDao;
public UserDao getUserDao() {
return userDao;
}
//以set注入的方式注入UserDao
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public void register() {
userDao.save();
System.out.println("userDao: " + userDao);
}
测试类:
@Test
public void test2() {
XmlBeanFactory context = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
//scope=prototype注入失效
UserService userService = (UserService) context.getBean("userService");
UserService userService1 = (UserService) context.getBean("userService");
userService.register();
userService1.register();
}
运行结果:两次userService调用的userDao是同一个对象,但是UserDao是多例对象,就会出现注入失效的问题
UserDaoImpl.save
userDao: edu.hzb.first.UserDaoImpl@72b6cbcc
UserDaoImpl.save
userDao: edu.hzb.first.UserDaoImpl@72b6cbcc
二、解决方法
每次从Spring容器中获取多例的 UserDao都是不同的,所以可以让Spring容器来完成UserDao的注入
@Test
public void test2() {
XmlBeanFactory context = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
UserDao userDao = (UserDao) context.getBean("userDao");
UserDao userDao1 = (UserDao) context.getBean("userDao");
//getBean获取的时候,scope=prototype的多例对象,每次获取的都是不同的
System.out.println(userDao1);
System.out.println(userDao);
}
//运行结果
edu.hzb.first.UserDaoImpl@a7e666
edu.hzb.first.UserDaoImpl@68bbe345
改进后的代码:
通过BeanFactoryAware接口,在UserServiceImpl中注入Bean工厂,从而从工厂中获取UserDao。
public class UserServiceImpl implements UserService, BeanFactoryAware {
private UserDao userDao;
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
//不通过set注入的方式注入UserDao
// public UserDao getUserDao() {
// return userDao;
// }
//
// public void setUserDao(UserDao userDao) {
// this.userDao = userDao;
// }
@Override
public void register() {
UserDao userDao = (UserDao) beanFactory.getBean("userDao");
userDao.save();
System.out.println("userDao: " + userDao);
}
}
文章讨论了在Spring框架中,当Singleton单例对象尝试注入Prototype多例对象时,会导致每次获取到的多例对象相同,从而产生注入失效的问题。为了解决这个问题,文章提出了让Spring容器在需要时动态获取Prototype对象的方法,即通过实现BeanFactoryAware接口,在需要使用多例对象时,从Bean工厂中动态获取,确保每次获取到的是一个新的实例。
1344

被折叠的 条评论
为什么被折叠?



