一、问题
在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);
}
}