【Spring5.x】解决在注入时scope属性失效

作者: zhl 分类: Spring 发布时间: 2024-05-13 09:05
<bean id="userDAO" class="com.zhl.UserDAOImpl" scope="prototype"/>
<bean id="userService" class="com.zhl.UserServiceImpl">
    <property name="userDAO" ref="userDAO"/>
</bean>
package com.zhl;

/**
 * <p>使用注入的方式获取 userDAO
 *
 * @author zhl
 * @since 2024-05-11 18:23
 */
public class UserServiceImpl implements UserService{
    private UserDAO userDAO;

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

    public UserDAO getUserDAO() {
        return userDAO;
    }
    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }
}
public class SpringTest{
    /**
     * 测试 scope 属性失效
     *  根据<bean id="userDAO"  获取 userDAO 对象
     */
    @Test
    public void scopeInvalidTest1() {
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        UserDAO userDAO = (UserDAO) beanFactory.getBean("userDAO");
        UserDAO userDAO1 = (UserDAO) beanFactory.getBean("userDAO");
        userDAO.save();
        userDAO1.save();

        System.out.println(userDAO);    //com.zhl.UserDAOImpl@3dd4520b
        System.out.println(userDAO1);   //com.zhl.UserDAOImpl@5ae63ade
    }
    /**
    * 测试 scope 属性失效
    *   根据 <bean id="userService" 获取 userService 对象
    */
    @Test
    public void scopeInvalidTest2() {
        BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        UserService userService = (UserService) beanFactory.getBean("userService");
        UserService userService1 = (UserService) beanFactory.getBean("userService");
        // 在 UserService实现类register方法中调用并打印 userDAO
        userService.register();
        userService1.register();
    }
}

在Spring的配置工厂中设置 userDAO 为prototype非单例,每getBean()一次就创建一个新的userDAO对象。

  • 测试1:
  • 测试2:

在UserServiceImpl中进行业务操作时,userDAO 必须保证线程安全,可以上锁,每次只能获取一个 userDAO 对象,但是这样效率太低,可以给每个线程分配一个userDAO。
在测试二有两个线程,userDAO对象始终为一个,说明在注入时,scope属性会失效。

解决方法

不使用注入,service类实现 BeanFactoryAware接口

<bean id="userDAO" class="com.zhl.UserDAOImpl" scope="prototype"/>
<bean id="userService" class="com.zhl.UserServiceImpl"/>
package com.zhl;

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

/**
 * <p>实现 BeanFactoryAware 传入 BeanFactory,通过 getBean() 获取 
 *
 * @author zhl
 * @since 2024-05-11 18:23
 */
public class UserServiceImpl implements UserService, BeanFactoryAware {

    private BeanFactory beanFactory;

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

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}
  • 测试结果:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注